forked from pointfreeco/episode-code-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
5e1a05b
commit c119ae9
Showing
13 changed files
with
860 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## [Point-Free](https://www.pointfree.co) | ||
|
||
> #### This directory contains code from Point-Free Episode: [SwiftUI Navigation: Stacks](https://www.pointfree.co/episodes/ep213-swiftui-navigation-stacks) | ||
> | ||
> When all-new SwiftUI navigation tools were announced at WWDC, the one that got the most attention by far was NavigationStack, which powers navigation with an array. It is extremely powerful, but comes with trade-offs and new complexities. |
469 changes: 469 additions & 0 deletions
469
0213-navigation-stacks-pt3/StackExploration/StackExploration.xcodeproj/project.pbxproj
Large diffs are not rendered by default.
Oops, something went wrong.
7 changes: 7 additions & 0 deletions
7
.../StackExploration/StackExploration.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
8 changes: 8 additions & 0 deletions
8
...tion/StackExploration.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>IDEDidComputeMac32BitWarning</key> | ||
<true/> | ||
</dict> | ||
</plist> |
11 changes: 11 additions & 0 deletions
11
...-pt3/StackExploration/StackExploration/Assets.xcassets/AccentColor.colorset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"colors" : [ | ||
{ | ||
"idiom" : "universal" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
13 changes: 13 additions & 0 deletions
13
...ks-pt3/StackExploration/StackExploration/Assets.xcassets/AppIcon.appiconset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"idiom" : "universal", | ||
"platform" : "ios", | ||
"size" : "1024x1024" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
0213-navigation-stacks-pt3/StackExploration/StackExploration/Assets.xcassets/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
271 changes: 271 additions & 0 deletions
271
0213-navigation-stacks-pt3/StackExploration/StackExploration/ContentView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,271 @@ | ||
import SwiftUI | ||
|
||
//struct CounterDestination: Hashable { | ||
// var initialCount = 0 | ||
// var fact: FactSheetState? | ||
//} | ||
|
||
class AppModel: ObservableObject { | ||
@Published var path: [Destination] { | ||
didSet { | ||
self.bind() | ||
} | ||
} | ||
|
||
init(path: [Destination] = []) { | ||
self.path = path | ||
self.bind() | ||
} | ||
|
||
enum Destination: Hashable { | ||
case counter(CounterModel) | ||
case letter(String) | ||
} | ||
|
||
func bind() { | ||
for destination in self.path { | ||
switch destination { | ||
case let .counter(model): | ||
model.onTapLetter = { [weak self] letter in | ||
guard let self else { return } | ||
self.path.append(.letter(letter)) | ||
} | ||
model.onTapNumber = { [weak self] number in | ||
guard let self else { return } | ||
self.path.append(.counter(CounterModel(count: number))) | ||
} | ||
|
||
case .letter: | ||
break | ||
} | ||
} | ||
} | ||
} | ||
|
||
struct ContentView: View { | ||
@ObservedObject var model: AppModel | ||
// { | ||
// var path = NavigationPath() | ||
// path.append("A") | ||
// path.append("B") | ||
// path.append("C") | ||
// path.append(CounterModel(count: 42)) | ||
// path.append( | ||
// CounterModel( | ||
// count: 1_000, | ||
// fact: FactSheetState(message: "1,000 is the number of words a picture is worth.") | ||
// ) | ||
// ) | ||
// return path | ||
// }() | ||
|
||
var body: some View { | ||
VStack { | ||
Button { | ||
self.randomStackButtonTapped() | ||
} label: { | ||
Text("Random stack") | ||
} | ||
Button { | ||
var count = 0 | ||
for destination in self.model.path { | ||
guard case let .counter(counter) = destination | ||
else { continue } | ||
count += counter.count | ||
} | ||
print("Sum", count) | ||
} label: { | ||
Text("Sum the counts") | ||
} | ||
NavigationStack(path: self.$model.path) { | ||
ListView() | ||
.navigationDestination(for: AppModel.Destination.self) { destination in | ||
switch destination { | ||
case let .counter(model): | ||
CounterView(model: model) | ||
case let .letter(letter): | ||
ListView() | ||
.navigationTitle(Text(letter)) | ||
} | ||
} | ||
// .navigationDestination(for: String.self) { letter in | ||
// ListView() | ||
// .navigationTitle(Text(letter)) | ||
// } | ||
// .navigationDestination(for: CounterModel.self) { model in | ||
// CounterView(model: model) | ||
//// ListView() | ||
//// .navigationTitle(Text("\(number)")) | ||
// } | ||
.navigationTitle("Root") | ||
} | ||
.onChange(of: self.model.path) { path in | ||
dump(path) | ||
} | ||
} | ||
} | ||
|
||
func randomStackButtonTapped() { | ||
self.model.path = [] | ||
for _ in 0...Int.random(in: 3...6) { | ||
if Bool.random() { | ||
self.model.path.append(.counter(CounterModel(count: Int.random(in: 1...1_000)))) | ||
} else { | ||
self.model.path.append( | ||
.letter( | ||
String( | ||
Character( | ||
UnicodeScalar( | ||
UInt32.random( | ||
in: "A".unicodeScalars.first!.value..."Z".unicodeScalars.first!.value | ||
) | ||
)! | ||
) | ||
) | ||
) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
class CounterModel: ObservableObject, Hashable { | ||
@Published var count = 0 | ||
@Published var fact: FactSheetState? | ||
|
||
var onTapNumber: (Int) -> Void = { _ in } | ||
var onTapLetter: (String) -> Void = { _ in } | ||
|
||
init( | ||
count: Int = 0, | ||
fact: FactSheetState? = nil | ||
) { | ||
self.count = count | ||
self.fact = fact | ||
} | ||
|
||
func numberButtonTapped(number: Int) { | ||
self.onTapNumber(number) | ||
} | ||
|
||
func letterButtonTapped(letter: String) { | ||
self.onTapLetter(letter) | ||
} | ||
|
||
func decrementButtonTapped() { | ||
self.count -= 1 | ||
} | ||
func incrementButtonTapped() { | ||
self.count += 1 | ||
} | ||
func factButtonTapped() { | ||
Task { @MainActor in | ||
let (data, _) = try await URLSession.shared | ||
.data(from: URL(string: "http://numbersapi.com/\(self.count)")!) | ||
self.fact = FactSheetState( | ||
message: String(decoding: data, as: UTF8.self) | ||
) | ||
} | ||
} | ||
|
||
static func == (lhs: CounterModel, rhs: CounterModel) -> Bool { | ||
lhs === rhs | ||
} | ||
|
||
func hash(into hasher: inout Hasher) { | ||
hasher.combine(ObjectIdentifier(self)) | ||
} | ||
} | ||
|
||
struct CounterView: View { | ||
@ObservedObject var model: CounterModel | ||
// @StateObject var model = CounterModel() | ||
|
||
var body: some View { | ||
List { | ||
HStack { | ||
Button("-") { self.model.decrementButtonTapped() } | ||
Text("\(self.model.count)") | ||
Button("+") { self.model.incrementButtonTapped() } | ||
} | ||
.buttonStyle(.borderless) | ||
|
||
Button { | ||
self.model.factButtonTapped() | ||
} label: { | ||
Text("Number fact") | ||
} | ||
.buttonStyle(.borderless) | ||
|
||
Section { | ||
Button { | ||
self.model.letterButtonTapped(letter: "A") | ||
} label: { | ||
Text("Go to screen A") | ||
} | ||
Button { | ||
self.model.letterButtonTapped(letter: "B") | ||
} label: { | ||
Text("Go to screen B") | ||
} | ||
Button { | ||
self.model.letterButtonTapped(letter: "C") | ||
} label: { | ||
Text("Go to screen C") | ||
} | ||
Button { | ||
self.model.numberButtonTapped(number: self.model.count) | ||
} label: { | ||
Text("Go to screen \(self.model.count)") | ||
} | ||
// .buttonStyle(.navigationLink) | ||
|
||
// NavigationLink(value: ContentView.Destination.letter("A")) { | ||
// Text("Go to screen A") | ||
// } | ||
// NavigationLink(value: ContentView.Destination.letter("B")) { | ||
// Text("Go to screen B") | ||
// } | ||
// NavigationLink(value: ContentView.Destination.letter("C")) { | ||
// Text("Go to screen C") | ||
// } | ||
// NavigationLink(value: ContentView.Destination.counter(CounterModel(count: self.model.count))) { | ||
// Text("Go to screen \(self.model.count)") | ||
// } | ||
} | ||
} | ||
.sheet(item: self.$model.fact) { fact in | ||
Text(fact.message) | ||
} | ||
.navigationTitle(Text("\(self.model.count)")) | ||
} | ||
} | ||
struct FactSheetState: Identifiable, Hashable { | ||
var message = "" | ||
var id: Self { self } | ||
} | ||
|
||
struct ContentView_Previews: PreviewProvider { | ||
static var previews: some View { | ||
ContentView(model: AppModel()) | ||
} | ||
} | ||
|
||
struct ListView: View { | ||
var body: some View { | ||
List { | ||
NavigationLink(value: AppModel.Destination.letter("A")) { | ||
Text("Go to screen A") | ||
} | ||
NavigationLink(value: AppModel.Destination.letter("B")) { | ||
Text("Go to screen B") | ||
} | ||
NavigationLink(value: AppModel.Destination.letter("C")) { | ||
Text("Go to screen C") | ||
} | ||
NavigationLink(value: AppModel.Destination.counter(CounterModel(count: 42))) { | ||
Text("Go to screen 42") | ||
} | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
0213-navigation-stacks-pt3/StackExploration/StackExploration/Info.plist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
<plist version="1.0"> | ||
<dict> | ||
<key>NSAppTransportSecurity</key> | ||
<dict> | ||
<key>NSAllowsArbitraryLoads</key> | ||
<true/> | ||
</dict> | ||
</dict> | ||
</plist> |
6 changes: 6 additions & 0 deletions
6
...3/StackExploration/StackExploration/Preview Content/Preview Assets.xcassets/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
0213-navigation-stacks-pt3/StackExploration/StackExploration/StackExplorationApp.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import SwiftUI | ||
|
||
@main | ||
struct StackExplorationApp: App { | ||
var body: some Scene { | ||
WindowGroup { | ||
ContentView( | ||
model: AppModel( | ||
path: [ | ||
.counter(CounterModel()) | ||
] | ||
) | ||
) | ||
} | ||
} | ||
} |
Oops, something went wrong.