The iOS world has been a-buzz ever since SwiftUI came on the scene. Twitter threads exploded, countless books about the topic went into presale, and recruiters on LinkedIn seem to want us to have 3+ years of experience with the UI Toolkit. So, what’s all the fuss about, is it worth it, and how can you become part of the action?
10. List {
ForEach(contents, id: .id) { partialContent in
NavigationLink(destination: ContentListingView() {
CardView(model: CardViewModel.transform(partialContent))
.listRowBackground(self.bgColor)
.background(self.bgColor)
}
.listRowBackground(self.bgColor)
.background(self.bgColor)
}
.listRowBackground(self.bgColor)
.background(self.bgColor) ???
How to !@#$ change the BG color
of a table view?!
30. a View is a struct
is a value type
is immutable
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
31. Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@ObservedObject
@State
@EnvironmentObject
32. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage own state
Data Flow/
33. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Data Flow/
34. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
onView()
var body: some View {
if isOn { onView() }
}
}
Data Flow/
35. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
onView()
offView()
var body: some View {
if isOn { onView() }
else { offView() }
}
}
Data Flow/
36. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
var body: some View {
if isOn { onView() }
else { offView() }
}
}
onView()
offView()
var body: some View {
Button(action: {
//toggle between on/off
}) {
if isOn { onView() }
else { offView() }
}
}
Data Flow/
37. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@State var isOn: Bool = false
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { onView() }
else { offView() }
}
}
onView()
offView()
Data Flow/
38. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
= state; source of truth
describes View
mutates State
Data Flow/
39. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
40. = state owner; source of truth
Checkmark
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
41. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
= state owner; source of truth
Event
Data Flow/
42. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
New State
= state; source of truth
Data Flow/
43. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
Data Flow/
44. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
struct Lamp: View {
var isOn: Bool
}
struct Room: View {
var isLampOn: Bool
var body: some View {
Lamp(isOn: isLampOn)
}
}
Data Flow/
45. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
struct Lamp: View {
var isOn: Bool
}
struct Room: View {
@State var isLampOn: Bool
var body: some View {
Lamp(isOn: isLampOn)
}
}
Data Flow/
46. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
struct Lamp: View {
@Binding var isOn: Bool
}
struct Room: View {
@State var isLampOn: Bool
var body: some View {
Lamp(isOn: isLampOn)
}
}
Data Flow/
47. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
struct Lamp: View {
@Binding var isOn: Bool
}
struct Room: View {
@State var isLampOn: Bool
var body: some View {
Lamp(isOn: $isLampOn)
}
}
Data Flow/
48. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
@EnvironmentObject
@ObservedObject
Data Flow/
49. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
@EnvironmentObject
@ObservedObject
@State
Dynamic View Properties
<> @Binding
Data Flow/
50. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Filters
Data Flow/
51. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
52. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
Data Flow/
53. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
}
Data Flow/
54. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
}
Data Flow/
55. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
}
struct Checkbox: View {
@Binding var isOn: Bool
}
Data Flow/
56. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
struct Checkbox: View {
@Binding var isOn: Bool
}
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
var body: some View {
CheckboxView(isOn: $isOn)
}
}
Data Flow/
57. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
= state; source of truth
Data Flow/
58. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
59. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
= state; source of truth
Parent
TitleCheckbox
Checkbox
Data Flow/
60. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
= state; source of truth
Parent
TitleCheckbox
Checkbox
Data Flow/
61. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@State @Binding @Binding @Binding<> <> <> <>
Data Flow/
63. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Custom controls shouldn’t be using @State.
Data Flow Through SwiftUI
Data Flow/
64. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Custom controls shouldn’t be using @State. *
(* or very, very sparingly)
Data Flow Through SwiftUI
Data Flow/
65. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersLibrary
Data Flow/
66. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
Data Flow/
67. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
FiltersState
Data Flow/
68. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
FiltersState
applied
Data Flow/
69. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
FiltersState
editable
applied
Data Flow/
70. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
Close/Apply
areFiltersSame
FiltersState
editable
applied
Data Flow/
71. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@ObservedObject
@State
@EnvironmentObject
Data Flow/
72. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@ObservedObject
@State
@EnvironmentObject
Data Flow/
73. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage a View’s own state
2. @State <> @Binding, to communicate between Views
3. @ObservedObject
@EnvironmentObject
to communicate between a View and its model
<> @ObservableObject
Data Flow/
74. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
class FiltersState {
var applied: [Filter] = []
var all: [Filter] = [] {
var editable: [Filter]
var areFiltersSame: Bool {
return all.elementsEqual(editable)
}
func clearAll() {...}
func update(filter: Filter) {...}
}
Data Flow/
75. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
class FiltersState: ObservableObject {
var applied: [Filter] = []
var all: [Filter] = []
var editable: [Filter]
var areFiltersSame: Bool {
return all.elementsEqual(editable)
}
func clearAll() {...}
func update(filter: Filter) {...}
}
Data Flow/
76. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
class FiltersState: ObservableObject {
@Published var applied: [Filter] = []
@Published var all: [Filter] = []
@Published var editable: [Filter]
var areFiltersSame: Bool {
return all.elementsEqual(editable)
}
func clearAll() {...}
func update(filter: Filter) {...}
}
Data Flow/
77. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
class FiltersState: ObservableObject {
private(set) var objectWillChange = PassthroughSubject<Void, Never>()
@Published var applied: [Filter] = []
@Published var all: [Filter] = []
@Published var editable: [Filter]
var areFiltersSame: Bool {
return all.elementsEqual(editable)
}
func clearAll() {...}
func update(filter: Filter) {...}
}
Data Flow/
78. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
class FiltersState: ObservableObject {
private(set) var objectWillChange = PassthroughSubject<Void, Never>()
@Published var applied: [Filter] = []
@Published var all: [Filter] = []
@Published var editable: [Filter]
var areFiltersSame: Bool {
return all.elementsEqual(editable)
}
func clearAll () {
objectWillChange.send(())
}
func update(filter: Filter) {...}
}
Data Flow/
79. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
struct TitleCheckbox: View {
@State var isOn: Bool = false
var name: String
var body: some View {
CheckboxBindingView(isOn: $isOn)
}
}
struct Checkbox: View {
@Binding var isOn: Bool
var body: some View {…}
}
Checkbox
Data Flow/
80. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
81. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Heading
Filters List
Close/Apply
Data Flow/
82. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Heading
FiltersList
FiltersView
FiltersState
Close/Apply
Data Flow/
83. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersView().environmentObject(state)
FiltersView(state: state)
@ObservedObject
@EnvironmentObject
Data Flow/
84. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersView().environmentObject(state)
FiltersView(state: state)
@ObservedObject
@EnvironmentObject
🤔
Singleton!?
Data Flow/
85. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct FiltersView: View {
@EnvironmentObject var state: FiltersState
var body: some View {
return VStack {
Heading()
filters()
button()
}
}
func button() -> ButtonView {...}
func filters() -> some View {...}
}
Heading
FiltersList
Button
Data Flow/
86. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
Data Flow/
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
var body: some View {...}
}
87. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
Data Flow/
struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {...}
}
88. struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {...}
}
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct FiltersView: View {
@EnvironmentObject var state: FiltersState
var body: some View {...}
}
Data Flow/
89. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox(name: name)
TitleCheckbox(isOn: $isOn, name: name)
Data Flow/
90. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct FiltersView2: View {
@EnvironmentObject var state: FiltersState
var body: some View {...}
private func filters() -> some View {
VStack() {
ForEach(state.editable, id: .self) { filter in
TitleCheckbox(isOn: Binding<Bool> , name: String )
}
}
}
}
Data Flow/
91. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct FiltersView2: View {
@EnvironmentObject var state: FiltersState
var body: some View {...}
private func filtersList() -> some View {
VStack() {
ForEach(state.editable, id: .self) { filter in
TitleCheckbox(isOn: Binding<Bool> , name: String )
}
}
}
}
filter
TitleCheckbox(isOn: Binding<Bool> , name: String )
Data Flow/
92. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@EnvironmentObject var state: FiltersState
Data Flow/
93. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@EnvironmentObject var state: FiltersState
Data Flow/
94. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct FiltersView2: View {
@EnvironmentObject var state: FiltersState
var body: some View {...}
private func filtersList() -> some View {
VStack() {
}
}
}
ForEach($state.editable, id:.self) { filter in
TitleCheckbox(isOn: filter.isOn, name: filter.name)
}
Data Flow/
95. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct FiltersView2: View {
@EnvironmentObject var state: FiltersState
var body: some View {...}
private func filtersList() -> some View {
VStack() {
}
}
}
ForEach(0..<state.editable.count) { index in
TitleCheckbox(isOn: self.$filters.editable[index].isOn,
name: self.filters.editable[index].name)
}
Data Flow/
96. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Fatal error: Accessing State<Array<Filter>> outside View.body:
file /BuildRoot/Library/Caches/com.apple.xbs/Sources/
Monoceros_Sim/Monoceros-24.4/Core/State.swift, line 44
Data Flow/
97. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Fatal error: Accessing State<Array<Filter>> outside View.body:
file /BuildRoot/Library/Caches/com.apple.xbs/Sources/
Monoceros_Sim/Monoceros-24.4/Core/State.swift, line 44
ForEach(0..<state.editable.count) { index in
TitleCheckbox(isOn: self.$state.editable[index].isOn,
name: self.state.editable[index].name)
}
Data Flow/
98. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
Do not access @State
outride of View.body!
🙅 📵👎
99. ForEach<Range<Int>, Int, AppliedFilterView> count (2) != its
initial count (0). `ForEach(_:content:)` should only be used
for *constant* data. Instead conform data to `Identifiable` or
use `ForEach(_:id:content:)` and provide an explicit `id`!
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
ForEach(0..<state.editable.count) { index in
TitleCheckbox(isOn: self.$state.editable[index].isOn,
name: self.state.editable[index].name)
}
Data Flow/
100. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Fatal error: Accessing State<Array<Filter>> outside View.body:
file /BuildRoot/Library/Caches/com.apple.xbs/Sources/
Monoceros_Sim/Monoceros-24.4/Core/State.swift, line 44
Data Flow/
101. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Fatal error: Accessing State<Array<Filter>> outside View.body:
file /BuildRoot/Library/Caches/com.apple.xbs/Sources/
Monoceros_Sim/Monoceros-24.4/Core/State.swift, line 44
Data Flow/
102. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
🤨
Fatal error: Accessing State<Array<Filter>> outside View.body:
file /BuildRoot/Library/Caches/com.apple.xbs/Sources/
Monoceros_Sim/Monoceros-24.4/Core/State.swift, line 44
Data Flow/
103. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
104. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
😩
Data Flow/
105. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct TitleCheckbox: View {
@State var filter: Filter
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
😩
Data Flow/
106. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Composing complex interfaces
Data Flow/
107. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
private func filtersList() -> some View {
return VStack {
ForEach(state.editable, id:.self) { filter in
TitleCheckbox(filter: filter)
}
}
}
struct TitleCheckbox: View {
@State var filter: Filter
var body: some View {
Checkbox(filter: $filter)
}
}
Data Flow/
108. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox(filter: filter)
TitleCheckbox(isOn: $isOn, name: name)
Data Flow/
109. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
110. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
TitleCheckbox
Checkbox
FiltersView
Data Flow/
111. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
TitleCheckbox
Checkbox
FiltersView
Data Flow/
112. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
TitleCheckbox
Checkbox
FiltersView
👿
Data Flow/
113. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
TitleCheckbox
Checkbox
FiltersView
Data Flow/
114. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersView
FiltersState; @EnvironmentObject
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
115. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
List
FiltersView
FiltersState; @EnvironmentObject
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
116. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
List
FiltersView
FiltersState; @EnvironmentObject
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
117. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
List
FiltersView
FiltersState; @EnvironmentObject
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
118. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
119. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
@EnvironmentObject var state: FiltersState
Data Flow/
120. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@
var body: some View {
Button(action: {
self.filter.isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
@EnvironmentObject var state: FiltersState
self.filter.isOn.toggle()
Data Flow/
121. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@
var body: some View {
Button(action: {
let index = state.editable.firstIndex(of: filter)!
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
@EnvironmentObject var state: FiltersState
let index = state.editable.firstIndex(of: filter)!
Data Flow/
122. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@
var body: some View {
Button(action: {
self.state.editable[self.index].isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
@EnvironmentObject var state: FiltersState
let index = state.editable.firstIndex(of: filter)!
self.state.editable[self.index].isOn.toggle()
Data Flow/
123. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@
var body: some View {
Button(action: {
self.state.editable[self.index].isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
@EnvironmentObject var state: FiltersState
let index = state.editable.firstIndex(of: filter)!
self.state.editable[self.index].isOn.toggle() 🤪
Data Flow/
124. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct LandmarkDetail: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
}
var body: some View {
Button(action: {
self.userData.landmarks[self.landmarkIndex].isFavorite.toggle()
}) {
if self.userData.landmarks[self.landmarkIndex].isFavorite {
Image(systemName: "star.fill")
.foregroundColor(Color.yellow)
} else {
Image(systemName: "star")
.foregroundColor(Color.gray)
}
}
}
Data Flow/
125. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@
var body: some View {
Button(action: {
self.state.editable[self.index].isOn.toggle()
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
@EnvironmentObject var state: FiltersState
let index = state.editable.firstIndex(of: filter)!
self.state.editable[self.index].isOn.toggle()
Data Flow/
126. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@EnvironmentObject var state: FiltersState
var body: some View {
Button(action: {
let index = state.editable.firstIndex(of: filter)!
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
self.state.editable[self.index].isOn.toggle()
Data Flow/
127. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@EnvironmentObject var state: FiltersState
var body: some View {
Button(action: {
let index = state.editable.firstIndex(of: filter)!
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
self.state.editable[self.index].isOn.toggle()
@Binding var filter: Filter
Data Flow/
128. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@EnvironmentObject var state: FiltersState
var body: some View {
Button(action: {
let index = state.editable.firstIndex(of: filter)!
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
let index = state.editable.firstIndex(of: filter)!
self.state.editable[self.index].isOn.toggle()
@Binding var filter: Filter
🤯
Data Flow/
129. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
@Binding var filter: Filter
@EnvironmentObject var state: FiltersState
var body: some View {
Button(action: {
let index = state.editable.firstIndex(of: filter)!
}) {
if filter.isOn { OnView() }
else { OffView() }
}
}
}
let filtered = state.editable.filter { $0.name == filter.name }.first!
let index = state.editable.firstIndex(of: filtered)!
self.state.editable[self.index].isOn.toggle()
@Binding var filter: Filter
Data Flow/
130. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Data Flow/
131. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Not reusable.
Data Flow/
132. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Not reusable.
Code smells…
let filtered = state.editable.filter { $0.name == filter.name }.first!
let index = state.editable.firstIndex(of: filtered)!
self.state.editable[self.index].isOn.toggle()
🤔
Data Flow/
133. try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Not reusable.
Code smells…
let filtered = state.editable.filter { $0.name == filter.name }.first!
let index = state.editable.firstIndex(of: filtered)!
self.state.editable[self.index].isOn.toggle()
🤔
🙅
Data Flow/
143. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
144. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
145. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
3. Passing data between Views (and Models)
146. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
3. Passing data between Views (and Models)
4. Challenges of data-binding for Lists
147. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
3. Passing data between Views
4. Challenges of data-binding for Lists
5. Approach the unknown by experimenting
148. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
3. Passing data between Views
4. Challenges of data-binding for Lists
5. Approach the unknown by experimenting
149. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Views
Data Reusable Specific
Constant Enumerated + Binding Identifiable + Binding
Dynamic Identifiable + Callbacks Identifiable + Binding
150. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
ForEach(state.editable, id:.self) { filter in
TitleCheckbox(isOn: $filter.isOn, name: filter.name)
}
struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
151. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
ForEach(state.editable, id:.self) { filter in
TitleCheckbox(isOn: $filter.isOn, name: filter.name)
}
struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
152. Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
ForEach(state.editable, id:.self) { filter in
TitleCheckbox(isOn: $filter.isOn, name: filter.name)
}
struct TitleCheckbox: View {
@Binding var isOn: Bool
var name: String
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
@Binding var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}