Balbas Code

SwiftUIにおける@ObservedObjectの再初期化問題とその解決策

公開日: 2023-10-13 23:16:42

SwiftUIで作成されたビューモデルSampleViewModelが予期しないタイミングで初期化されてしまう問題が発生しました。具体的には、テキストエディタに文字を入力するごとにビューモデルが初期化され、その結果としてinputTextプロパティのデフォルト値がテキストエディタに反映されてしまいました。


サンプルコード(問題発生時)


struct ContentView: View {
@ObservedObject var viewModel = SampleViewModel()

var body: some View {
VStack {
TextEditor(text: $viewModel.inputText)
}
}
}

class SampleViewModel: ObservableObject {
@Published var inputText: String = "Default Text"
}

 


原因


SampleViewModel@ObservedObjectとしてビュー内で直接初期化されていました。しかし、@ObservedObjectはビューの再描画が行われるたびに関連するオブジェクトも再生成される可能性があるため、この振る舞いが原因で問題が発生していました。


解決策


@ObservedObjectの代わりに@StateObjectを使用することで、ビューモデルのインスタンスが安定して同一のものとして保持されるようにしました。これにより、ビューの再描画時にビューモデルが再初期化されることがなくなり、問題は解消されました。


サンプルコード(問題解決後)


struct ContentView: View {
@StateObject var viewModel = SampleViewModel()

var body: some View {
VStack {
TextEditor(text: $viewModel.inputText)
}
}
}

class SampleViewModel: ObservableObject {
@Published var inputText: String = "Default Text"
}

 


まとめ


SwiftUIは非常に便利なフレームワークであり、多くのデベロッパーに愛されていますが、特定の状況で予期しない動作や問題が発生することがあります。今回取り上げた問題は、ビューモデルが意図せずに再初期化されるというものでした。


この問題の要点は以下の通りです:
1. @ObservedObjectプロパティラッパー:このプロパティラッパーは、ビューの再構築時にオブジェクトの新しいインスタンスを生成する可能性があります。
2. @StateObjectプロパティラッパー:このプロパティラッパーは、ビューが再構築されてもオブジェクトのインスタンスが保持されます。この特性により、@StateObjectはビューモデルのような外部オブジェクトの管理に適しています。
3. 解決策:@ObservedObjectを使用する場合、ビューモデルが予期しないタイミングで再初期化される問題を防ぐために、@StateObjectを使用することを推奨します。

SwiftUIを使用する際には、プロパティラッパーの違いとその動作を理解しておくことが重要です。この知識を持っておくことで、意図しない動作やバグを回避し、アプリの安定性を高めることができます。