Apple のサンプルプロジェクト Updating an App to Use Swift Concurrency の全体像の把握とサンプルプロジェクトを作成した人の気持ちを考えてみる為の資料。
6QEBUJOHBO"QQUP6TF4XJGU$PODVSSFODZղઆ
View Slide
ΞϓϦͷ֓ཁ
"QQҰཡ 5PQ %SJOL-JTU $PNQMJDBUJPO
5PQ %SJOL-JTU )FBMUI,JU
ΞϓϦ मਖ਼લͷߏ
$POUFOU7JFX$PGGFF5SBDLFS7JFX%SJOL-JTU7JFX%SJOL%SJOL5ZQF$PGGFF%BUB)FBMUI,JU$POUSPMMFS&OUJUZ 0CTFSWBCMF0CKFDU7JFX$POUSPMMFS
&OUJUZstruct Drink: Hashable, Codable {let mgCaffeine: Doublelet date: Datelet uuid: UUID}enum DrinkType: Int, CaseIterable, Identifiable {case smallCoffeecase mediumCoffeecase largeCoffeecase singleEspressocase doubleEspressocase quadEspressocase blackTeacase greenTeacase softDrinkcase energyDrinkcase chocolate}%SJOL %SJOL5ZQF
7JFX$PGGFF5SBDLFS7JFX %SJOL-JTU7JFX
7JFX$PGGFF%BUB 0CTFSWBCMF0CKFDU$PGGFF5SBDLFS7JFX %SJOL-JTU7JFX@EnvironmentObject var coffeeData: CoffeeDatacoffeeData.currentMGCaffeineStringcoffeeData.totalCupsTodayStringcoffeeData.addDrink(…)
$PGGFF%BUBclass CoffeeData: ObservableObject {lazy var healthKitController = HealthKitController(withModel: self)// @Published ͳͷͰϝΠϯεϨου͔Βૢ࡞͢Δඞཁ͕͋Δ@Published public var currentDrinks: [Drink] = []// …func save() {/* currentDrinks ΛσΟεΫอଘ(όοΫάϥϯυॲཧ) */}func load() {/* currentDrinks ΛσΟεΫ͔ΒಡΈࠐΈ(όοΫάϥϯυॲཧ) */}}
)FBMUI,JU$POUSPMMFS// … runs the query on an anonymous background queue.private let store = HKHealthStore()class HealthKitController {private weak var model: CoffeeData?// …public func loadNewDataFromHealthKit(…) { /* … */ }public func save(drink: Drink) { /* … */ }private func updateModel(newDrinks: [Drink], deletedDrinks: Set) {// …// @Published ͳͷͰϝΠϯεϨου͔Βૢ࡞͢Δඞཁ͕͋Δmodel?.currentDrinks = drinks}}
$PGGFF5SBDLFS7JFX$PGGFF%BUB )FBMUI,JU$POUSPMMFS%SJOL-JTU7JFX.BJO5ISFBE#BDLHSPVOE5ISFBEDVSSFOU%SJOLTNPEFMDVSSFOU%SJOLTESJOLT),)FBMUI4UPSFTUPSFFYFDVUF RVFSZ SFTVMUT)BOEMFS%FWJDF3FBE8SJUF%BUBBEE%SJOL
4XJGU$PODVSSFODZҠߦͷํ
$PGGFF5SBDLFS7JFX$PGGFF%BUB )FBMUI,JU$POUSPMMFS%SJOL-JTU7JFX.BJO5ISFBE#BDLHSPVOE5ISFBEDVSSFOU%SJOLT),)FBMUI4UPSFTUPSFFYFDVUF RVFSZ SFTVMUT)BOEMFS%FWJDF3FBE8SJUF%BUBBEE%SJOL͜͜Λཧ͍ͨ͠NPEFMDVSSFOU%SJOLTESJOLT
$PGGFF5SBDLFS7JFX$PGGFF%BUB )FBMUI,JU$POUSPMMFS%SJOL-JTU7JFX.BJO5ISFBE#BDLHSPVOE5ISFBEDVSSFOU%SJOLT),)FBMUI4UPSFTUPSFFYFDVUF RVFSZ SFTVMUT)BOEMFS%FWJDF3FBE8SJUF%BUBBEE%SJOLଞͷΦϒδΣΫτͷϓϩύςΟΛߋ৽͢ΔͷͰͳ͘ɺBDUPSؒͷΓͱΓʹஔ͖͑Δඞཁ͕͋ΔNPEFMDVSSFOU%SJOLTESJOLT
$PGGFF5SBDLFS7JFX$PGGFF%BUB )FBMUI,JU$POUSPMMFS%SJOL-JTU7JFX.BJO"DUPS"DUPSDVSSFOU%SJOLT),)FBMUI4UPSF%FWJDF3FBE8SJUF%BUBBEE%SJOL$PGGFF%BUB4UPSFVQEBUF.PEFM OFX%SJOLTEFMFUFE%SJOLTಥʹਤ
ཧ͞Ε֤ͨΞΫλʔͷׂ
$PGGFF%BUB@MainActorclass CoffeeData: ObservableObject {lazy var healthKitController = HealthKitController(withModel: self)private let store = CoffeeDataStore()@Published public private(set) var currentDrinks: [Drink] = []// …}currentDrinks private(set) ʹͳΓ CoffeeData ͰͷΈߋ৽͞ΕΔΑ͏ʹ৽ͨʹఆٛͨ͠ CoffeeDataStore ϓϩύςΟͱͯ͠อ͍࣋ͯ͠ΔHealthKitController ͱͷؔੑมΘΒͣ
$PGGFF%BUB4UPSFactor CoffeeDataStore {func save(_ currentDrinks: [Drink]) {/* currentDrinks ΛσΟεΫอଘ */}func load() -> [Drink] {/* currentDrinks ΛσΟεΫ͔ΒಡΈࠐΈ */}// …}લͷؔͦΕͧΕ save(), load()save ʹҾ͕ɺload ʹฦΓ͕͍ͨΞΫλʔؒͰඞཁͳใΛΓͱΓ͢ΔͨΊͷΠϯλʔϑΣʔε
)FBMUI,JU$POUSPMMFSactor HealthKitController {private weak var model: CoffeeData?func loadNewDataFromHealthKit() async -> Bool {// …let (samples, deletedSamples, newAnchor) = try await queryHealthKit()// …await model?.updateModel(newDrinks: newDrinks, deletedDrinks: deletedDrinks)// …}// …}CoffeeData ͱͷؔੑมΘΒͣ currentDrink Λߋ৽͢ΔͷͰͳ͘ɺupdateModel Λհͯ͠ߋ৽͢ΔΫΤϦͷ࣮ߦ෦ͷهड़͕ΦγϟϨʹ
$PGGFF5SBDLFS7JFX$PGGFF%BUB )FBMUI,JU$POUSPMMFS%SJOL-JTU7JFX.BJO"DUPS"DUPSDVSSFOU%SJOLT),)FBMUI4UPSF%FWJDF3FBE8SJUF%BUBBEE%SJOL$PGGFF%BUB4UPSFVQEBUF.PEFM OFX%SJOLTEFMFUFE%SJOLT࠶ܝ