アプリ全体で使用している変数をアプリ終了時や復帰時などにSave/Loadする場合は、SceneDelegateでEnvironmentObjectを使用したい場合があります。
EnvironmentObjectで使用するクラスはObservableObjectです。なのでSceneDelegateでは@ObservedObjectで宣言しておき、その変数をViewに渡すことでSceneDelegateからアクセスできます。
class ObsObj: ObservableObject {
@Published var text:String = "Test"
}
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
@ObservedObject var envObj = ObsObj()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView().environmentObject(envObj)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
envObj.Test()
}
func sceneDidBecomeActive(_ scene: UIScene) {
}
func sceneWillResignActive(_ scene: UIScene) {
}
func sceneWillEnterForeground(_ scene: UIScene) {
}
func sceneDidEnterBackground(_ scene: UIScene) {
}
}
@EnvironmentObjectはViewからはどこからでもアクセス出来て便利ですが、SceneDelegateで使用した場合は注意が必要です。
ダメなパターン。
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
@EnvironmentObject var envObj:ObsObj
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView().environmentObject(ObsObj())
//以下略
}
}
Fatal error: No ObservableObject of type ObsObj found. A View.environmentObject(_:) for ObsObj may be missing as an ancestor of this view.: file SwiftUI, line 0
ビルドは通りますが、いざ実行すると上記のエラーが出ます。要は使用するクラスよりも上位のクラスで.environmentObject()を実行しろということです。
rootViewをSceneDelegateで設定しているので、親のViewはおそらく無いと思いますのでObservedObjectで宣言する必要があります。
EnvironmentObjectそのままを使う方法があればコメントにお願いいたします。
コメント