SwiftUI for Production
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
🥰 Like SwiftUI?
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
🛠 Used SwiftUI?
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
🥳
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
🥰
+
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI
🤔🤩😑
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
Where the compiler thinks the problem is.
Where the problem actually is.
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
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?!
private func filtersView() -> some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: .filterSpacing) {
ForEach(filters.appliedFilters, id: .self) { filter in
AppliedFilterView(filter: filter, type: .default) {
self.contentsMC.updateFilters(newFilters: self.filters)
}
}
}
}
.padding([.top], .filtersPaddingTop)
}
private func filtersView() -> some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: .filterSpacing) {
ForEach(filters.appliedFilters, id: .self) { filter in
AppliedFilterView(filter: filter, type: .default) {
self.contentsMC.updateFilters(newFilters: self.filters)
}
}
}
}
.padding([.top], .filtersPaddingTop)
}
🤯
SwiftUI
🤔🤩😑
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Content List Filters
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
Content List Filters
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Content List Filters
SwiftUI/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI
🤔🤩😑
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Declarative UI framework.
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
“View is a function of state, not a
sequence of events.”
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Off
On
SwiftUI/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
class CheckmarkBox: UIView {
private var isOn: Bool
init(isOn: Bool) {
self.isOn = isOn
super.init(frame: .zero)
setupViews()
}
}
1. Create
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Off
On
class CheckmarkBox: UIView {
private var isOn: Bool
init(isOn: Bool) {
self.isOn = isOn
super.init(frame: .zero)
setupViews()
}
}
1. Create 2. Configure
SwiftUI/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Off
On
class CheckmarkBox: UIView {
private var isOn: Bool
init(isOn: Bool) {
self.isOn = isOn
super.init(frame: .zero)
setupViews()
}
}
1. Create 2. Configure
SwiftUI/
3. Respond
Parent
Child
1: Tap
2: Change
3: Inform
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
UIKit
SwiftUI/
Parent
Child
1: Tap
2: Change
3: Inform
😩
Multidirectional
data flow.
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. Create 2. Configure 3. Respond
SwiftUI/
struct CheckmarkView: View {
@State var isOn: Bool = false
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { onView()
} else { offView()
}
}
}
}
?Off
On
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
UIKit
SwiftUI/
SwiftUI
Parent
Child
2: Inform
1: Tap
3: Change
Parent
Child
1: Tap
2: Change
3: Inform
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
SwiftUI/
SwiftUI
Parent
Child
2: Inform
1: Tap
3: Change
🥳
Unidirectional
data flow.
Data Flow~
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
👑👑👑
immutablemutable
Data Flow/
a View is a struct
is a value type
is immutable
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@ObservedObject
@State
@EnvironmentObject
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage own state
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
onView()
var body: some View {
if isOn { onView() }
}
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
onView()
offView()
var body: some View {
if isOn { onView() }
else { offView() }
}
}
Data Flow/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
= state; source of truth
describes View
mutates State
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
= state owner; source of truth
Checkmark
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
= state owner; source of truth
Event
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
New State
= state; source of truth
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. @State, to manage your own state
2. @State <> @Binding, to communicate between views
Data Flow/
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/
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/
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/
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/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Filters
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
struct TitleCheckbox: View {
@State var isOn: Bool
var name: String
}
Data Flow/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox
Checkbox
= state; source of truth
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
= state; source of truth
Parent
TitleCheckbox
Checkbox
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
= state; source of truth
Parent
TitleCheckbox
Checkbox
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@State @Binding @Binding @Binding<> <> <> <>
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@State @Binding @Binding @Binding<> <> <> <>
@Binding @Binding @Binding<> <> <> <>
@Binding @Binding @Binding<> <> <> <>
@Binding<> <>
@Binding<>
@Binding<>
<>
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Custom controls shouldn’t be using @State.
Data Flow Through SwiftUI
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Custom controls shouldn’t be using @State. *
(* or very, very sparingly)
Data Flow Through SwiftUI
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersLibrary
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
FiltersState
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
FiltersState
applied
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
FiltersState
editable
applied
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Library Filters
Close/Apply
areFiltersSame
FiltersState
editable
applied
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@ObservedObject
@State
@EnvironmentObject
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@ObservedObject
@State
@EnvironmentObject
Data Flow/
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/
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/
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/
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/
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/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Heading
Filters List
Close/Apply
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Heading
FiltersList
FiltersView
FiltersState
Close/Apply
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersView().environmentObject(state)
FiltersView(state: state)
@ObservedObject
@EnvironmentObject
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
FiltersView().environmentObject(state)
FiltersView(state: state)
@ObservedObject
@EnvironmentObject
🤔
Singleton!?
Data Flow/
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/
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 {...}
}
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 {...}
}
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox(name: name)
TitleCheckbox(isOn: $isOn, name: name)
Data Flow/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@EnvironmentObject var state: FiltersState
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
@EnvironmentObject var state: FiltersState
Data Flow/
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/
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/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
Do not access @State
outride of View.body!
🙅 📵👎
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/
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/
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/
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/
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/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Composing complex interfaces
Data Flow/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
TitleCheckbox(filter: filter)
TitleCheckbox(isOn: $isOn, name: name)
Data Flow/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Checkbox
Not reusable.
Data Flow/
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/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1:31
Introduction
1:31
Memory Sizing2
1:31
Optionals & Asserts3
Snapchat
Robinhood
Course Episodes
9:41
Video Playback Speed
1080p
720p
540p
360p
Sign Out
1080pVideo Playback Speed
1080pDownloads Quality
OffSubtitles
Downloads (WiFi only)
Settings
9:41
Data Flow/
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/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct TitleCheckbox: View {
var isOn: Bool
var name: String
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
struct Checkbox: View {
var isOn: Bool
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
var isOn: Bool
var onChange: (Bool) -> Void
var body: some View {
Button(action: {
self.isOn.toggle()
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
struct TitleCheckbox: View {
var isOn: Bool
var name: String
var onChange: (Bool) -> Void
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: $isOn)
}
}
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
struct Checkbox: View {
var isOn: Bool
var onChange: (Bool) -> Void
var body: some View {
Button(action: {
self.onChange(!self.isOn)
}) {
if isOn { OnView() }
else { OffView() }
}
}
}
struct TitleCheckbox: View {
var isOn: Bool
var name: String
var onChange: (Bool) -> Void
var body: some View {
HStack {
TitleText(text: name)
Spacer()
Checkbox(isOn: isOn, onChange: onChange)
}
}
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
func filtersList() -> some View {
VStack {
ForEach(state.editable, id:.self) { filter in
TitleCheckbox(isOn: filter.isOn, name: filter.name) { isOn in
guard let index = self.state.editable.firstIndex(of: filter)
else { return }
self.state.editable[index].isOn = isOn
}
}
}
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
func filtersList() -> some View {
VStack {
ForEach(state.editable, id:.self) { filter in
TitleCheckbox(isOn: filter.isOn, name: filter.name) { isOn in
guard let index = self.state.editable.firstIndex(of: filter)
else { return }
self.state.editable[index].isOn = isOn
}
}
}
}
Data Flow/
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Data Flow/
Recap
🙌
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. What SwiftUI is
2. SwiftUI VS UIKit
3. Passing data between Views (and Models)
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
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
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
Recap
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
Views
Data Reusable Specific
Constant Enumerated + Binding Identifiable + Binding
Dynamic Identifiable + Callbacks Identifiable + Binding
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() }
}
}
}
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() }
}
}
}
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() }
}
}
}
What Now?
🙌
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
1. Conference repo https://github.com/leamars/trySwift2019
2. UIKit translation to SwiftUI https://goshdarnswiftui.com
3. Facebook iOS Components: https://youtu.be/XhXC4SKOGfQ
4. Jetpack Compose: https://youtu.be/VsStyq4Lzxo
5. @hellosunschein on Twitter
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
What Now
Thank You!
🥳🙏👻
try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein

SwiftUI For Production | try! Swift 2019

  • 1.
    SwiftUI for Production try!Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
  • 2.
    🥰 Like SwiftUI? try!Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
  • 3.
    🛠 Used SwiftUI? try!Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
  • 4.
    🥳 try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein
  • 5.
    🥰 + try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein
  • 6.
    SwiftUI 🤔🤩😑 try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein
  • 8.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein SwiftUI/ Where the compiler thinks the problem is. Where the problem actually is.
  • 9.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein SwiftUI/
  • 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?!
  • 11.
    private func filtersView()-> some View { ScrollView(.horizontal, showsIndicators: false) { HStack(alignment: .top, spacing: .filterSpacing) { ForEach(filters.appliedFilters, id: .self) { filter in AppliedFilterView(filter: filter, type: .default) { self.contentsMC.updateFilters(newFilters: self.filters) } } } } .padding([.top], .filtersPaddingTop) }
  • 12.
    private func filtersView()-> some View { ScrollView(.horizontal, showsIndicators: false) { HStack(alignment: .top, spacing: .filterSpacing) { ForEach(filters.appliedFilters, id: .self) { filter in AppliedFilterView(filter: filter, type: .default) { self.contentsMC.updateFilters(newFilters: self.filters) } } } } .padding([.top], .filtersPaddingTop) } 🤯
  • 13.
    SwiftUI 🤔🤩😑 try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein
  • 14.
    Content List Filters try!Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein SwiftUI/
  • 15.
    Content List Filters try!Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein SwiftUI/
  • 16.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein Content List Filters SwiftUI/ try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
  • 17.
    SwiftUI 🤔🤩😑 try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein
  • 18.
    Declarative UI framework. try!Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein SwiftUI/
  • 19.
    “View is afunction of state, not a sequence of events.” try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein SwiftUI/
  • 20.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein Off On SwiftUI/
  • 21.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein SwiftUI/ class CheckmarkBox: UIView { private var isOn: Bool init(isOn: Bool) { self.isOn = isOn super.init(frame: .zero) setupViews() } } 1. Create
  • 22.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein Off On class CheckmarkBox: UIView { private var isOn: Bool init(isOn: Bool) { self.isOn = isOn super.init(frame: .zero) setupViews() } } 1. Create 2. Configure SwiftUI/
  • 23.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein Off On class CheckmarkBox: UIView { private var isOn: Bool init(isOn: Bool) { self.isOn = isOn super.init(frame: .zero) setupViews() } } 1. Create 2. Configure SwiftUI/ 3. Respond Parent Child 1: Tap 2: Change 3: Inform
  • 24.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein UIKit SwiftUI/ Parent Child 1: Tap 2: Change 3: Inform 😩 Multidirectional data flow.
  • 25.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein 1. Create 2. Configure 3. Respond SwiftUI/ struct CheckmarkView: View { @State var isOn: Bool = false var body: some View { Button(action: { self.isOn.toggle() }) { if isOn { onView() } else { offView() } } } } ?Off On
  • 26.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein UIKit SwiftUI/ SwiftUI Parent Child 2: Inform 1: Tap 3: Change Parent Child 1: Tap 2: Change 3: Inform
  • 27.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein SwiftUI/ SwiftUI Parent Child 2: Inform 1: Tap 3: Change 🥳 Unidirectional data flow.
  • 28.
    Data Flow~ try! Swift2019 | Lea Marolt Sonnenschein | @hellosunschein 👑👑👑
  • 29.
  • 30.
    a View isa struct is a value type is immutable Data Flow/ try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein
  • 31.
    Data Flow/ try! Swift2019 | 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/
  • 62.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein @State @Binding @Binding @Binding<> <> <> <> @Binding @Binding @Binding<> <> <> <> @Binding @Binding @Binding<> <> <> <> @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/
  • 134.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein 1:31 Introduction 1:31 Memory Sizing2 1:31 Optionals & Asserts3 Snapchat Robinhood Course Episodes 9:41 Video Playback Speed 1080p 720p 540p 360p Sign Out 1080pVideo Playback Speed 1080pDownloads Quality OffSubtitles Downloads (WiFi only) Settings 9:41 Data Flow/
  • 135.
    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/
  • 136.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein struct TitleCheckbox: View { var isOn: Bool var name: String var body: some View { HStack { TitleText(text: name) Spacer() Checkbox(isOn: $isOn) } } } struct Checkbox: View { var isOn: Bool var body: some View { Button(action: { self.isOn.toggle() }) { if isOn { OnView() } else { OffView() } } } } Data Flow/
  • 137.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein struct Checkbox: View { var isOn: Bool var onChange: (Bool) -> Void var body: some View { Button(action: { self.isOn.toggle() }) { if isOn { OnView() } else { OffView() } } } } struct TitleCheckbox: View { var isOn: Bool var name: String var onChange: (Bool) -> Void var body: some View { HStack { TitleText(text: name) Spacer() Checkbox(isOn: $isOn) } } } Data Flow/
  • 138.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein struct Checkbox: View { var isOn: Bool var onChange: (Bool) -> Void var body: some View { Button(action: { self.onChange(!self.isOn) }) { if isOn { OnView() } else { OffView() } } } } struct TitleCheckbox: View { var isOn: Bool var name: String var onChange: (Bool) -> Void var body: some View { HStack { TitleText(text: name) Spacer() Checkbox(isOn: isOn, onChange: onChange) } } } Data Flow/
  • 139.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein func filtersList() -> some View { VStack { ForEach(state.editable, id:.self) { filter in TitleCheckbox(isOn: filter.isOn, name: filter.name) { isOn in guard let index = self.state.editable.firstIndex(of: filter) else { return } self.state.editable[index].isOn = isOn } } } } Data Flow/
  • 140.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein func filtersList() -> some View { VStack { ForEach(state.editable, id:.self) { filter in TitleCheckbox(isOn: filter.isOn, name: filter.name) { isOn in guard let index = self.state.editable.firstIndex(of: filter) else { return } self.state.editable[index].isOn = isOn } } } } Data Flow/
  • 141.
    try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein Data Flow/
  • 142.
    Recap 🙌 try! Swift 2019| Lea Marolt Sonnenschein | @hellosunschein
  • 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() } } } }
  • 153.
    What Now? 🙌 try! Swift2019 | Lea Marolt Sonnenschein | @hellosunschein
  • 154.
    1. Conference repohttps://github.com/leamars/trySwift2019 2. UIKit translation to SwiftUI https://goshdarnswiftui.com 3. Facebook iOS Components: https://youtu.be/XhXC4SKOGfQ 4. Jetpack Compose: https://youtu.be/VsStyq4Lzxo 5. @hellosunschein on Twitter try! Swift 2019 | Lea Marolt Sonnenschein | @hellosunschein What Now
  • 155.
    Thank You! 🥳🙏👻 try! Swift2019 | Lea Marolt Sonnenschein | @hellosunschein