Avatar
Avatar
koher
某所で話してたのは↓ですね。
Repositoryがオンメモリキャッシュを扱うかどうかに関わらず、僕はSingle source of truthとなる状態を扱うMainActorを設けるようにしています。より具体的には、Repository - Store - (ViewModel) - Viewという構造にしていて、Viewを超えて保持する状態を(MainActorである)Storeで保持しています。ViewModel(またはViewModelを省略してViewの状態や変更をViewが直接扱う場合はView)がStoreに対してデータの更新を要求すると、Storeは必要に応じてRepositoryを介してデータを取得し、自身の状態(@Publishedなプロパティ)を更新する形です。 Repositoryはあくまでデータアクセスを抽象化するためのものなので、キャッシュの有無は外から不可知なのが良いかと思います。なので、たとえRepositoryがオンメモリキャッシュを持っていてもStoreに相当するものは必要だと思いますし(Repositoryのキャッシュは状態を扱っているわけではないと思うので)、Store的なものがあればそれをMainActorにすることでUI(ViewまたはViewModel)から同期的にアクセスすることができます。
結局、CurrentValueSubject を Actor にしたもの(ConcurrentValueSubject)をさらに wrap して state を射影するくん(ProjectedValueSubject)を作って、これを ObservableObject に準拠させるくん(ViewBinding)を作ってことなきを得ました。 ConcurrentValueSubject: https://github.com/Kuniwak/BLEMacroApp/blob/7756662301f809b10926c3f0466a160cca6866de/Packages/Package/Sources/ConcurrentCombine/ConcurrentValueSubject.swift ProjectedValueSubject: https://github.com/Kuniwak/BLEMacroApp/blob/7756662301f809b10926c3f0466a160cca6866de/Packages/Package/Sources/ConcurrentCombine/ProjectedValueSubject.swift ViewBinding: https://github.com/Kuniwak/BLEMacroApp/blob/7756662301f809b10926c3f0466a160cca6866de/Packages/Package/Sources/ViewFoundation/ViewBinding.swift
8:33 AM
Model の世界では ProjectedValueSubject までしか知らなくて、View の世界から ViewBinding が登場するという設計です