Slide 1

Slide 1 text

0CTFSWBUJPO4BMMPX%JWF $ZCP[V.PCJMF.FFUVQ FMNFUBM$ZCP[V *OD

Slide 2

Slide 2 text

"CPVUNF !FM@NFUBM@ J04"QQ %FWFMPQFS J04ΞϓϦ։ൃ ڝഅ ରઓήʔϜ

Slide 3

Slide 3 text

8IBUJT0CTFSWBUJPO w ݎ࿚ɾλΠϓηʔϑɾߴύϑΥʔϚϯεͷΦϒβʔόʔύλʔϯΛఏڙ͢Δ w ϓϩύςΟͷมߋΛ௥੻͢ΔͨΊͷ৽͍͠4XJGUͷػೳ w 4XJGUͷ௨ৗͷܕͱҰॹʹಈ࡞͠ɺϚΫϩͰม׵͢Δ w A!0CTFSWBUJPOAΛ௥Ճ͢Δ͚ͩͰಈ͘ 0CTFSWBUJPO

Slide 4

Slide 4 text

8IZ0CTFSWBUJPO

Slide 5

Slide 5 text

8IZ0CTFSWBUJPO 0UIFSNFDIBOJTNTGPSPCTFSWBUJPOJO4XJGU w ,70 LFZWBMVFPCTFSWJOH w 0CTFSWBCMF0CKFDU

Slide 6

Slide 6 text

8IZ0CTFSWBUJPO 0UIFSNFDIBOJTNTGPSPCTFSWBUJPOJO4XJGU w ,70 LFZWBMVFPCTFSWJOH 
 ˠ/40CKFDUͷܧঝ͕ඞཁ 
 ˠΠϕϯτͷΠϯλʔηϓτ͔͠ఏڙ͞Εͳ͍ͷͰɺ௨஌͕XJMM4FUͱEJE4FUͷؒͰߦΘΕΔ ˠΠϕϯτཻ౓ʹ͸ॊೈੑ͕͋Δ͕ɺ߹੒ੑʹ͚ܽΔ 
 ˠ0CKFDUJWF$ϥϯλΠϜʹґଘ͢Δ 
 ˠLFZQBUIͰڧ͍ܕ෇͚͕͞Ε͍ͯΔʹ΋ؔΘΒͣɺ࣮ࡍ͸จࣈྻܕ෇͚͞Ε͍ͯΔ w 0CTFSWBCMF0CKFDU 
 ˠ%BSXJOͰ͔͠࢖͑ͳ͍ 
 ˠQSFDPODVSSFODZͳ$PNCJOF͕ඞཁ 
 ˠܕͷ४ڌ͚ͩͰͳ͘ɺ؍ଌ͞ΕΔϓϩύςΟʹA!1VCMJTIFEA͕ඞཁ ˠDPNQVUFEQSPQFSUZΛ௚઀؍ଌͰ͖ͳ͍ 
 ˠDIBOHFFWFOUͷ։࢝࣌ʹੜ੒͞ΕΔͷͰɺ৽͍͠஋͕ઃఆ͞ΕΔલʹશͯͷ஋͕ྲྀΕΔ

Slide 7

Slide 7 text

4PMVUJPOTUPQSPCMFNTPUIFSNFDIBOJTNTGPSPCTFSWBUJPO w A!0CTFSWBCMFAΞϊςʔγϣϯͰܕࣗମΛPCTFSWBCMFʹ͢Δ w 0CTFSWBCMFϚΫϩʹΑΓɺϓϩτίϧ४ڌͱϓϩύςΟͷτϥοΩϯάΛ࣮ ૷͢Δ 
 ˠϓϩύςΟ͝ͱʹݸผͷϚʔΩϯά͕ෆཁ 8IZ0CTFSWBUJPO

Slide 8

Slide 8 text

6TJOH0CTFSWBUJPO

Slide 9

Slide 9 text

6TJOH!0CTFSWBCMF 6TJOH0CTFSWBUJPO @Observable class FoodTruckModel { var orders: [Order] = [] var donuts = Donut.all }

Slide 10

Slide 10 text

6TJOH!0CTFSWBCMF 6TJOH0CTFSWBUJPO @Observable class FoodTruckModel { var orders: [Order] = [] var donuts = Donut.all } Ξϊςʔγϣϯ͸ҰՕॴ શϓϩύςΟ͕τϥοΩϯάͰ͖Δ

Slide 11

Slide 11 text

&YQBOE.BDSP 6TJOH0CTFSWBUJPO @Observable class FoodTruckModel { @ObservationTracked var orders: [Order] = [] @ObservationTracked var donuts = Donut.all @ObservationIgnored private let _$observationRegistrar = ObservationRegistrar() internal nonisolated func access( keyPath: KeyPath ) { _$observationRegistrar.access(self, keyPath: keyPath) } internal nonisolated func withMutation( keyPath: KeyPath, _ mutation: () throws -> T ) rethrows -> T { try _$observationRegistrar.withMutation(of: self, keyPath: keyPath, mutation) } @ObservationIgnored private var _orders: [Order] = [] @ObservationIgnored private var _donuts = Donut.all } extension FoodTruckModel : Observable {}

Slide 12

Slide 12 text

4XJGU6*QSPQFSUZUSBDLJOH 6TJOH0CTFSWBUJPO @Observable class FoodTruckModel { var orders: [Order] = [] var donuts = Donut.all } struct DonutMenu: View { let model: FoodTruckModel var body: some View { List { Section("Donuts") { ForEach(model.donuts) { donut in Text(donut.name) } Button("Add new donut") { model.addDonut() } } } } }

Slide 13

Slide 13 text

4XJGU6*QSPQFSUZUSBDLJOH 6TJOH0CTFSWBUJPO @Observable class FoodTruckModel { var orders: [Order] = [] var donuts = Donut.all } struct DonutMenu: View { let model: FoodTruckModel var body: some View { List { Section("Donuts") { ForEach(model.donuts) { donut in Text(donut.name) } Button("Add new donut") { model.addDonut() } } } } } Ξϊςʔγϣϯ͕ෆཁ

Slide 14

Slide 14 text

6TJOH1SPQFSUZ8SBQQFS

Slide 15

Slide 15 text

6TJOH!4UBUF 6TJOH1SPQFSUZ8SBQQFS struct DonutListView: View { var donutList: DonutList @State private var donutToAdd: Donut? var body: some View { List(donutList.donuts) { DonutView(donut: $0) } Button("Add Donut") { donutToAdd = Donut() } .sheet(item: $donutToAdd) { TextField("Name", text: $donutToAdd.name) Button("Save") { donutList.donuts.append(donutToAdd) donutToAdd = nil } Button("Cancel") { donutToAdd = nil } } } }

Slide 16

Slide 16 text

6TJOH!&OWJSPONFOU 6TJOH1SPQFSUZ8SBQQFS @Observable class Account { var userName: String? } struct FoodTruckMenuView : View { @Environment(Account.self) var account var body: some View { if let name = account.userName { HStack { Text(name); Button("Log out") { account.logOut() } } } else { Button("Login") { account.showLogin() } } } }

Slide 17

Slide 17 text

6TJOH!#JOEBCMF 6TJOH1SPQFSUZ8SBQQFS @Observable class Donut { var name: String } struct DonutView: View { @Bindable var donut: Donut var body: some View { TextField("Name", text: $donut.name) } }

Slide 18

Slide 18 text

4UPSJOH!0CTFSWBCMFUZQFTJO"SSBZ 6TJOH1SPQFSUZ8SBQQFS @Observable class Donut { var name: String } struct DonutList: View { var donuts: [Donut] var body: some View { List(donuts) { donut in HStack { Text(donut.name) Spacer() Button("Randomize") { donut.name = randomName() } } } } }

Slide 19

Slide 19 text

3FGFSFODFT

Slide 20

Slide 20 text

w %JTDPWFS0CTFSWBUJPOJO4XJGU6* 
 IUUQTEFWFMPQFSBQQMFDPNWJEFPTQMBZXXED w "QQMF%FWFMPQFS%PDVNFOUBUJPO0CTFSWBUJPO IUUQTEFWFMPQFSBQQMFDPNEPDVNFOUBUJPO0CTFSWBUJPO 3FGFSFODFT