5
3

More than 1 year has passed since last update.

【SwiftUi】StateObjectとObservedObjectの違い

Last updated at Posted at 2022-09-11

はじめに

ObservedObjectを用いたページにおいて、その上位ページの値がeventlistenerによって変化する度に現在のページが初期化されることがあった。
ViewModelからデータを共有する方法は大きくStateObjectObvservedObjectの2つがある。
よってこの2つの使い方や特徴をまとめる。

環境

Xcode 13.3.1

構成

APP
|   Mainview.swift
\ーchildrenPages
  |  ObservedObjectView.swift
  |  StateObjectView.swift

Code

MainView
class MainViewModel: ObservableObject {
    @Published var mainCount = 0
}

struct MaintView: View {
    
    @ObservedObject var viewmodel = MainViewModel()

    var body: some View {
        NavigationView {
            VStack{
                Text(viewmodel.mainCount.description)
                    .font(.title)
                
                NavigationLink("ObservedObject") {
                    ObservedOjectView(mainCount: $viewmodel.mainCount)
                }
                .font(.title)
                .padding()
                
                NavigationLink("StateObject") {
                    StateObjectView(mainCount: $viewmodel.mainCount )
                }
                .font(.title)
                .padding()
            }
        }
    }
}
StateObjectView
class StateObjectViewModel: ObservableObject {
    @Published var count = 0
    
    func addCount() {
        self.count += 1
    }
}

struct StateObjectView: View {
    @StateObject var viewmodel = StateObjectViewModel()
    @Binding var mainCount : Int
    
    var body: some View {
        VStack{
            Text("StateObject : \(viewmodel.count.description)")
                .font(.title)
                .padding()
                .onTapGesture {
                    viewmodel.addCount()
                }
            
            Button {
                self.mainCount += 1
            } label: {
                Text("change main view count")
                    .font(.title)
            }
            Text(self.mainCount.description)
                .font(.title)
        }
    }
}
ObservedObjectView
class ObservedOjectViewModel : ObservableObject {
    @Published var observedCount = 0
    
    func addCount() {
        self.observedCount += 1
    }
}

struct ObservedOjectView: View {
    @ObservedObject var viewmodel = ObservedOjectViewModel()
    @Binding var mainCount : Int
    
    var body: some View {
        VStack{
            Text("Observed : \(viewmodel.observedCount.description)")
                .font(.title)
                .padding()
                .onTapGesture {
                    viewmodel.addCount()
                }
            
            Button {
                self.mainCount += 1
            } label: {
                Text("change main view count")
                    .font(.title)
            }
            Text(self.mainCount.description)
                .font(.title)

        }
    }
}

Screen

Sep-11-2022 23-14-11.gif

@Bindingによって上位ページの値が変化するようにした。

@ObservedObject: 画面に入る時、初期化されない。 上位ページによって初期化される。
@StateObject: 画面に入る時、初期化される。 上位ページによって初期化されない。

DBを用いたプロジェクトでは値が頻繁に変化するので、@StateObjectを利用することが多いと思いました。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3