$30 off During Our Annual Pro Sale. View Details »

Updating an App to Use Swift Concurrency 解説

Updating an App to Use Swift Concurrency 解説

Apple のサンプルプロジェクト Updating an App to Use Swift Concurrency の全体像の把握とサンプルプロジェクトを作成した人の気持ちを考えてみる為の資料。

naru-jpn

May 12, 2022
Tweet

More Decks by naru-jpn

Other Decks in Programming

Transcript

  1. 6QEBUJOHBO"QQUP6TF4XJGU$PODVSSFODZ
    ղઆ

    View Slide

  2. ΞϓϦͷ֓ཁ

    View Slide

  3. "QQҰཡ 5PQ %SJOL-JTU $PNQMJDBUJPO

    View Slide

  4. 5PQ %SJOL-JTU )FBMUI,JU

    View Slide

  5. ΞϓϦ मਖ਼લ
    ͷߏ଄

    View Slide

  6. $POUFOU7JFX
    $PGGFF5SBDLFS7JFX
    %SJOL-JTU7JFX
    %SJOL
    %SJOL5ZQF
    $PGGFF%BUB
    )FBMUI,JU$POUSPMMFS
    &OUJUZ 0CTFSWBCMF0CKFDU
    7JFX
    $POUSPMMFS

    View Slide

  7. &OUJUZ
    struct Drink: Hashable, Codable {


    let mgCaffeine: Double


    let date: Date


    let uuid: UUID


    }
    enum DrinkType: Int, CaseIterable, Identifiable {


    case smallCoffee


    case mediumCoffee


    case largeCoffee


    case singleEspresso


    case doubleEspresso


    case quadEspresso


    case blackTea


    case greenTea


    case softDrink


    case energyDrink


    case chocolate


    }
    %SJOL %SJOL5ZQF

    View Slide

  8. 7JFX
    $PGGFF5SBDLFS7JFX %SJOL-JTU7JFX

    View Slide

  9. 7JFX$PGGFF%BUB 0CTFSWBCMF0CKFDU

    $PGGFF5SBDLFS7JFX %SJOL-JTU7JFX
    @EnvironmentObject var coffeeData: CoffeeData
    coffeeData.currentMGCaffeineString
    coffeeData.totalCupsTodayString
    coffeeData.addDrink(…)

    View Slide

  10. $PGGFF%BUB
    class CoffeeData: ObservableObject {


    lazy var healthKitController = HealthKitController(withModel: self)


    // @Published ͳͷͰϝΠϯεϨου͔Βૢ࡞͢Δඞཁ͕͋Δ


    @Published public var currentDrinks: [Drink] = []


    // …


    func save() {


    /* currentDrinks ΛσΟεΫ΁อଘ(όοΫάϥ΢ϯυॲཧ) */


    }


    func load() {


    /* currentDrinks ΛσΟεΫ͔ΒಡΈࠐΈ(όοΫάϥ΢ϯυॲཧ) */


    }


    }

    View Slide

  11. )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


    }


    }

    View Slide

  12. $PGGFF5SBDLFS7JFX
    $PGGFF%BUB )FBMUI,JU$POUSPMMFS
    %SJOL-JTU7JFX
    .BJO5ISFBE
    #BDLHSPVOE5ISFBE
    DVSSFOU%SJOLT
    NPEFMDVSSFOU%SJOLTESJOLT
    ),)FBMUI4UPSF
    TUPSFFYFDVUF RVFSZ
    SFTVMUT)BOEMFS
    %FWJDF
    3FBE8SJUF%BUB
    BEE%SJOL

    View Slide

  13. 4XJGU$PODVSSFODZҠߦͷํ਑

    View Slide

  14. $PGGFF5SBDLFS7JFX
    $PGGFF%BUB )FBMUI,JU$POUSPMMFS
    %SJOL-JTU7JFX
    .BJO5ISFBE
    #BDLHSPVOE5ISFBE
    DVSSFOU%SJOLT
    ),)FBMUI4UPSF
    TUPSFFYFDVUF RVFSZ
    SFTVMUT)BOEMFS
    %FWJDF
    3FBE8SJUF%BUB
    BEE%SJOL
    ͜͜Λ੔ཧ͍ͨ͠
    NPEFMDVSSFOU%SJOLTESJOLT

    View Slide

  15. $PGGFF5SBDLFS7JFX
    $PGGFF%BUB )FBMUI,JU$POUSPMMFS
    %SJOL-JTU7JFX
    .BJO5ISFBE
    #BDLHSPVOE5ISFBE
    DVSSFOU%SJOLT
    ),)FBMUI4UPSF
    TUPSFFYFDVUF RVFSZ
    SFTVMUT)BOEMFS
    %FWJDF
    3FBE8SJUF%BUB
    BEE%SJOL
    ௚઀ଞͷΦϒδΣΫτͷϓϩύςΟΛ
    ߋ৽͢ΔͷͰ͸ͳ͘ɺBDUPSؒͷ
    ΍ΓͱΓʹஔ͖׵͑Δඞཁ͕͋Δ
    NPEFMDVSSFOU%SJOLTESJOLT

    View Slide

  16. $PGGFF5SBDLFS7JFX
    $PGGFF%BUB )FBMUI,JU$POUSPMMFS
    %SJOL-JTU7JFX
    .BJO"DUPS
    "DUPS
    DVSSFOU%SJOLT
    ),)FBMUI4UPSF
    %FWJDF
    3FBE8SJUF%BUB
    BEE%SJOL
    $PGGFF%BUB4UPSF
    VQEBUF.PEFM OFX%SJOLTEFMFUFE%SJOLT

    ౜ಥʹ׬੒ਤ

    View Slide

  17. ੔ཧ͞Ε֤ͨΞΫλʔͷ໾ׂ

    View Slide

  18. $PGGFF%BUB
    @MainActor


    class 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 ͱͷؔ܎ੑ͸มΘΒͣ

    View Slide

  19. $PGGFF%BUB4UPSF
    actor CoffeeDataStore {


    func save(_ currentDrinks: [Drink]) {


    /* currentDrinks ΛσΟεΫ΁อଘ */


    }


    func load() -> [Drink] {


    /* currentDrinks ΛσΟεΫ͔ΒಡΈࠐΈ */


    }


    // …


    }
    ෼཭લͷؔ਺͸ͦΕͧΕ save(), load()
    save ʹ͸Ҿ਺͕ɺload ʹ͸ฦΓ஋͕෇͍ͨ
    ΞΫλʔؒͰඞཁͳ৘ใΛ΍ΓͱΓ͢ΔͨΊͷΠϯλʔϑΣʔε

    View Slide

  20. )FBMUI,JU$POUSPMMFS
    actor 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 Λհͯ͠ߋ৽͢Δ
    ΫΤϦͷ࣮ߦ෦෼ͷهड़͕ΦγϟϨʹ

    View Slide

  21. $PGGFF5SBDLFS7JFX
    $PGGFF%BUB )FBMUI,JU$POUSPMMFS
    %SJOL-JTU7JFX
    .BJO"DUPS
    "DUPS
    DVSSFOU%SJOLT
    ),)FBMUI4UPSF
    %FWJDF
    3FBE8SJUF%BUB
    BEE%SJOL
    $PGGFF%BUB4UPSF
    VQEBUF.PEFM OFX%SJOLTEFMFUFE%SJOLT

    ࠶ܝ

    View Slide