SwiftDataとSwiftDependenciesを同時に使おうとしたら詰まった話

SwiftDataをSwiftUIのView外で使う方法とSwiftDependenciesの相性問題が発生した話
SwiftDataのクエリはView上で定義したくないので、Managerクラスでクエリを実装していくことにすると、modelContainer
とmodelContext
をManagerに保持する必要がある。しかし、context.mainContainer
はMain Actorの産物なので、Managerのinitメソッドに@MainActor
を付与する必要がある。それが冒頭1つ目のリンクが示すソリューションなのだが…
この時、ManagerクラスをSwift-DependenciesのDIコンテナで保持しようとすると上手くいかない。
import Dependencies
private enum AppDataServiceKey: DependencyKey {
static let liveValue: any AppDataServiceProtocol = AppDataService() // <- Syntax Error! "Call to main actor-isolated initializer 'init()' in a synchronous nonisolated context"
}
extension DependencyValues {
var appDataService: any AppDataServiceProtocol {
get { self[AppDataServiceKey.self] }
set { self[AppDataServiceKey.self] = newValue }
}
}
調べてみるとライブラリのリポジトリにディスカッションがあった。
https://github.com/pointfreeco/swift-dependencies/discussions/310
However, typically one does not need to make the dependency itself
@MainActor
, and instead it can hold onto something that is@MainActor
and provide@MainActor
endpoints for accessing its state. I would suggest exploring ways of designing your dependency that does not require a@MainActor
initializer, and then things should work just fine.
とのことで、結論は、Dependency側に@MainActor
を付与しなくてもいい方法を模索してね、とのこと。
対処療法としては、
@Environment
プロパティラッパーをDIコンテナの代わりにする- Viewのinit引数でバケツリレーする
のどちらかを採るしかない。
SwiftDataのmodelContainerをMainActorに依存せずに取得する方法は無いものか・・・。

nafell
大学生、26卒エンジニア志望。アプリ開発サークルを設立し、lounas.jpのバックエンド・DB設計を行いました。2年後期にインターンで設計の手法(要件定義~詳細設計)を学び、IoTシステムの調査・開発を行いました。