Skip to content

Commit 0c0df05

Browse files
committed
Initial drop
An initial implementation of the `ViewController` protocol and associated infrastructure. Seems to work OK.
1 parent 6bda0fd commit 0c0df05

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+4243
-0
lines changed

.github/workflows/swift.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: Build and Test
2+
3+
on:
4+
push:
5+
pull_request:
6+
schedule:
7+
- cron: "0 9 * * 1"
8+
9+
jobs:
10+
nextstep:
11+
runs-on: macos-latest
12+
steps:
13+
- name: Select latest available Xcode
14+
uses: maxim-lobanov/[email protected]
15+
with:
16+
xcode-version: 13
17+
- name: Checkout Repository
18+
uses: actions/checkout@v2
19+
- name: Build Swift Debug Package
20+
run: swift build -c debug
21+
- name: Build Swift Release Package
22+
run: swift build -c release
23+
- name: Run Tests
24+
run: swift test

.gitignore

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Xcode
2+
#
3+
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4+
5+
## Build generated
6+
build/
7+
DerivedData/
8+
9+
## Various settings
10+
*.pbxuser
11+
!default.pbxuser
12+
*.mode1v3
13+
!default.mode1v3
14+
*.mode2v3
15+
!default.mode2v3
16+
*.perspectivev3
17+
!default.perspectivev3
18+
xcuserdata/
19+
20+
## Other
21+
*.moved-aside
22+
*.xccheckout
23+
*.xcscmblueprint
24+
25+
## Obj-C/Swift specific
26+
*.hmap
27+
*.ipa
28+
*.dSYM.zip
29+
*.dSYM
30+
31+
## Playgrounds
32+
timeline.xctimeline
33+
playground.xcworkspace
34+
35+
# Swift Package Manager
36+
#
37+
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38+
# Packages/
39+
# Package.pins
40+
.build/
41+
42+
# CocoaPods
43+
#
44+
# We recommend against adding the Pods directory to your .gitignore. However
45+
# you should judge for yourself, the pros and cons are mentioned at:
46+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47+
#
48+
# Pods/
49+
50+
# Carthage
51+
#
52+
# Add this line if you want to avoid checking in source code from Carthage dependencies.
53+
# Carthage/Checkouts
54+
55+
Carthage/Build
56+
57+
# fastlane
58+
#
59+
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60+
# screenshots whenever they are needed.
61+
# For more information about the recommended setup visit:
62+
# https://docs.fastlane.tools/best-practices/source-control/#source-control
63+
64+
fastlane/report.xml
65+
fastlane/Preview.html
66+
fastlane/screenshots
67+
fastlane/test_output

Package.swift

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// swift-tools-version:5.5
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "ViewController",
7+
platforms: [ .macOS(.v11), .iOS(.v15) ],
8+
products: [ .library(name: "ViewController", targets: [ "ViewController" ]) ],
9+
targets: [
10+
.target(name: "ViewController")
11+
]
12+
)

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# ViewController
2+
3+
ViewController's for SwiftUI.
4+
5+
WIP.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
//
2+
// AnyViewController.swift
3+
// ViewController
4+
//
5+
// Created by Helge Heß.
6+
// Copyright © 2022 ZeeZide GmbH. All rights reserved.
7+
//
8+
9+
import Combine
10+
import SwiftUI
11+
12+
/**
13+
* A type erased version of a (statically typed) ``ViewController``.
14+
*
15+
* If possible type erasure should be avoided.
16+
*
17+
* When a ``ViewController`` is pushed into the environment, it is pushed
18+
* as an `@EnvironmentObject` of its concrete type, but also as an
19+
* ``AnyViewController``. This allows access of all common methods
20+
* (e.g. ``ViewController/dismiss``).
21+
*
22+
* Example access:
23+
* ```swift
24+
* struct TitleLabel: View {
25+
*
26+
* @EnvironmentObject private var viewController : AnyViewController
27+
*
28+
* var body: some View {
29+
* Text(verbatim: viewController.title)
30+
* .font(.title)
31+
* }
32+
* }
33+
* ```
34+
*/
35+
public final class AnyViewController: ViewController {
36+
37+
public var id : ObjectIdentifier { ObjectIdentifier(viewController) }
38+
39+
public let viewController : _ViewController
40+
private var subscription : AnyCancellable?
41+
42+
@usableFromInline
43+
init<VC>(_ viewController: VC) where VC: ViewController {
44+
assert(!(viewController is AnyViewController),
45+
"Attempt to nest an AnyVC into another \(viewController)")
46+
47+
self.viewController = viewController
48+
49+
subscription = viewController.objectWillChange.sink { [weak self] _ in
50+
self?.objectWillChange.send()
51+
}
52+
}
53+
54+
/**
55+
* An initializer that avoids nesting `AnyViewController`s into themselves.
56+
*/
57+
@usableFromInline
58+
init(_ viewController: AnyViewController) {
59+
self.viewController = viewController.viewController
60+
61+
// TBD: Can't unwrap this?
62+
subscription = viewController.objectWillChange.sink {
63+
[weak self] _ in
64+
self?.objectWillChange.send()
65+
}
66+
}
67+
68+
69+
// MARK: - All the any
70+
// Those are typed erased by the base protocol already (_ViewController).
71+
72+
@inlinable
73+
public var contentView : AnyView { anyContentView }
74+
@inlinable
75+
public var anyContentView : AnyView { viewController.anyContentView }
76+
@inlinable
77+
public var controlledContentView : AnyView { anyControlledContentView }
78+
@inlinable
79+
public var anyControlledContentView : AnyView {
80+
viewController.anyControlledContentView
81+
}
82+
83+
84+
// MARK: - Titles
85+
86+
@inlinable
87+
public var title : String? {
88+
set { viewController.title = newValue }
89+
get { viewController.title }
90+
}
91+
92+
@inlinable
93+
public var navigationTitle : String { viewController.navigationTitle }
94+
95+
96+
// MARK: - Represented Object
97+
98+
@inlinable
99+
public var representedObject : Any? {
100+
set { anyRepresentedObject = newValue }
101+
get { anyRepresentedObject }
102+
}
103+
@inlinable
104+
public var anyRepresentedObject : Any? {
105+
set { viewController.anyRepresentedObject = newValue }
106+
get { viewController.anyRepresentedObject }
107+
}
108+
109+
110+
// MARK: - Presentation
111+
112+
@inlinable
113+
public var presentedViewController : _ViewController? {
114+
get { viewController.presentedViewController }
115+
}
116+
@inlinable
117+
public var activePresentations : [ ViewControllerPresentation ] {
118+
set { viewController.activePresentations = newValue }
119+
get { viewController.activePresentations }
120+
}
121+
@inlinable
122+
public var presentingViewController : _ViewController? {
123+
set { viewController.presentingViewController = newValue }
124+
get { viewController.presentingViewController }
125+
}
126+
127+
@inlinable
128+
public func willAppear() { viewController.willAppear() }
129+
@inlinable
130+
public func willDisappear() { viewController.willDisappear() }
131+
132+
@inlinable
133+
public func present<VC>(_ viewController: VC,
134+
mode: ViewControllerPresentationMode)
135+
where VC: ViewController
136+
{
137+
self.viewController.present(viewController, mode: mode)
138+
}
139+
@inlinable
140+
public func present<VC: ViewController>(_ viewController: VC) {
141+
self.viewController.present(viewController)
142+
}
143+
@inlinable
144+
public func dismiss() { viewController.dismiss() } // TBD: really unwrap?
145+
146+
147+
@inlinable
148+
public func show<VC: ViewController>(_ viewController: VC) {
149+
self.viewController.show(viewController)
150+
}
151+
152+
@inlinable
153+
public func showDetail<VC: ViewController>(_ viewController: VC){
154+
self.viewController.showDetail(viewController)
155+
}
156+
157+
@inlinable
158+
public func show<VC, OwnerVC>(_ viewController: VC, in owner: OwnerVC)
159+
where VC: ViewController, OwnerVC: _ViewController
160+
{
161+
self.viewController.show(viewController, in: owner)
162+
}
163+
@inlinable
164+
public func showDetail<VC, OwnerVC>(_ viewController: VC, in owner: OwnerVC)
165+
where VC: ViewController, OwnerVC: _ViewController
166+
{
167+
self.viewController.showDetail(viewController, in: owner)
168+
}
169+
170+
171+
// MARK: - Hierarchy
172+
173+
@inlinable
174+
public var children : [ _ViewController ] {
175+
set { viewController.children = newValue }
176+
get { viewController.children }
177+
}
178+
179+
@inlinable
180+
public var parent : _ViewController? {
181+
set { viewController.parent = newValue }
182+
get { viewController.parent }
183+
}
184+
185+
@inlinable
186+
public func willMove(toParent parent: _ViewController?) {
187+
viewController.willMove(toParent: parent)
188+
}
189+
190+
@inlinable
191+
public func didMove(toParent parent: _ViewController?) {
192+
viewController.didMove(toParent: parent)
193+
}
194+
195+
@inlinable
196+
public func addChild<VC: ViewController>(_ viewController: VC) {
197+
self.viewController.addChild(viewController)
198+
}
199+
@inlinable
200+
public func removeFromParent() {
201+
viewController.removeFromParent() // TBD: really unwrap?
202+
}
203+
204+
205+
// MARK: - Better Description
206+
207+
@inlinable
208+
public var description: String { "<Any: \(viewController)>" }
209+
@inlinable
210+
public func appendAttributes(to description: inout String) {}
211+
}

0 commit comments

Comments
 (0)