SwiftUIの基本を身につけたい方はこちら

【SwiftUI】@ObservedObjectの使い方を徹底解説

この記事では、@ObservedObjectの使い方を解説していきたいと思います。

ObservedObjectオブザードオブジェクトとは?

簡単に言うと、@ObservedObjectとは、@Stateを複数同時に宣言できるクラスのことです。

@Stateの場合は、Viewごとに変数を宣言して使いますが、@ObservedObjectはクラスなので複数の変数をまとめて宣言して、複数のViewから使うことができます。

厳密にはちょっと違いますが、イメージ的にはこんな感じです。

使い方

使い方としては、ObservableObjectを準拠させたclass内に、@Stateの代わりに@Publishedを定義して、使いたいViewで@ObservedObjectで宣言して使います。

ちょっとややこしいので、サンプルコードを見ながら解説していきます。

以下のコードが@ObservedObjectを使ったサンプルコードです。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import SwiftUI
class Fruits: ObservableObject {
@Published var name = "りんご"
@Published var price = 100
}
struct ContentView: View {
@ObservedObject var fruits = Fruits()
var body: some View {
VStack {
Text("\(fruits.name)一個\(fruits.price)円です")
.padding()
Button("10円値上げする") {
fruits.price += 10
}
}
}
}
import SwiftUI class Fruits: ObservableObject { @Published var name = "りんご" @Published var price = 100 } struct ContentView: View { @ObservedObject var fruits = Fruits() var body: some View { VStack { Text("\(fruits.name)一個\(fruits.price)円です") .padding() Button("10円値上げする") { fruits.price += 10 } } } }
import SwiftUI

class Fruits: ObservableObject {
    @Published var name = "りんご"
    @Published var price = 100
}

struct ContentView: View {
    @ObservedObject var fruits = Fruits()
    
    var body: some View {
        VStack {
            Text("\(fruits.name)一個\(fruits.price)円です")
                .padding()
            Button("10円値上げする") {
                fruits.price += 10
            }
        }
    }
}
コード解説

まず、FruitsというObservableObjectプロトコルに準拠したclassを定義します。

その中に、@Publishedをつけて変数を宣言します。@Publishedは@Stateと同じようなものだと思ってください。

そして、使いたいViewで@ObservedObjectをつけてfruitsという名前でインスタンス化します。

インスタンス化したら、fruits.nameや、fruits.priceと言うふうに@Stateと同じく使えます。値の更新をすると@Stateと同じく再描画されすぐに画面に反映されます。

別のViewと共有する

まとめて共有する

@Stateの場合は、@Bindingで渡していましたが、@ObservedObjectの場合は、インスタンスで渡してあげると全てのデータまとめて渡すことができます。

以下のコードは、BViewでfruitsの名前を変更するサンプルコードです。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Fruits: ObservableObject {
@Published var name = "りんご"
@Published var price = 100
}
struct ContentView: View {
@ObservedObject var fruits = Fruits()
@State var isShowBView = false
var body: some View {
VStack {
Text("\(fruits.name)一個\(fruits.price)円です")
.padding()
Button("10円値上げする") {
fruits.price += 10
}
.padding()
Button("BViewへ遷移") {
isShowBView = true
}
}
.sheet(isPresented: $isShowBView) {
BView(fruits: fruits)
}
}
}
struct BView: View {
@ObservedObject var fruits: Fruits
var body: some View {
Button("みかんに変える") {
fruits.name = "みかん"
}
}
}
class Fruits: ObservableObject { @Published var name = "りんご" @Published var price = 100 } struct ContentView: View { @ObservedObject var fruits = Fruits() @State var isShowBView = false var body: some View { VStack { Text("\(fruits.name)一個\(fruits.price)円です") .padding() Button("10円値上げする") { fruits.price += 10 } .padding() Button("BViewへ遷移") { isShowBView = true } } .sheet(isPresented: $isShowBView) { BView(fruits: fruits) } } } struct BView: View { @ObservedObject var fruits: Fruits var body: some View { Button("みかんに変える") { fruits.name = "みかん" } } }
class Fruits: ObservableObject {
    @Published var name = "りんご"
    @Published var price = 100
}

struct ContentView: View {
    @ObservedObject var fruits = Fruits()
    @State var isShowBView = false
    
    var body: some View {
        VStack {
            Text("\(fruits.name)一個\(fruits.price)円です")
                .padding()
            Button("10円値上げする") {
                fruits.price += 10
            }
            .padding()
            Button("BViewへ遷移") {
                isShowBView = true
            }
        }
        .sheet(isPresented: $isShowBView) {
            BView(fruits: fruits)
        }
    }
}

struct BView: View {
    @ObservedObject var fruits: Fruits
    
    var body: some View {
        Button("みかんに変える") {
            fruits.name = "みかん"
        }
    }
}
コード解説

BViewで、@ObservedObject var fruits: Fruitsというように書くことで、@Bindingのように、ContentViewのfruitsと紐づけることができます。

一部分だけ共有する

@Stateと同じく1つの値なら、@Bindingでも渡すことができます。挙動的には上記と全く変わりません。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Fruits: ObservableObject {
@Published var name = "りんご"
@Published var price = 100
}
struct ContentView: View {
@ObservedObject var fruits = Fruits()
@State var isShowBView = false
var body: some View {
VStack {
Text("\(fruits.name)一個\(fruits.price)円です")
.padding()
Button("10円値上げする") {
fruits.price += 10
}
.padding()
Button("BViewへ遷移") {
isShowBView = true
}
}
.sheet(isPresented: $isShowBView) {
BView(fruitsName: $fruits.name)
}
}
}
struct BView: View {
@Binding var fruitsName: String
var body: some View {
Button("みかんに変える") {
fruitsName = "みかん"
}
}
}
class Fruits: ObservableObject { @Published var name = "りんご" @Published var price = 100 } struct ContentView: View { @ObservedObject var fruits = Fruits() @State var isShowBView = false var body: some View { VStack { Text("\(fruits.name)一個\(fruits.price)円です") .padding() Button("10円値上げする") { fruits.price += 10 } .padding() Button("BViewへ遷移") { isShowBView = true } } .sheet(isPresented: $isShowBView) { BView(fruitsName: $fruits.name) } } } struct BView: View { @Binding var fruitsName: String var body: some View { Button("みかんに変える") { fruitsName = "みかん" } } }
class Fruits: ObservableObject {
    @Published var name = "りんご"
    @Published var price = 100
}

struct ContentView: View {
    @ObservedObject var fruits = Fruits()
    @State var isShowBView = false
    
    var body: some View {
        VStack {
            Text("\(fruits.name)一個\(fruits.price)円です")
                .padding()
            Button("10円値上げする") {
                fruits.price += 10
            }
            .padding()
            Button("BViewへ遷移") {
                isShowBView = true
            }
        }
        .sheet(isPresented: $isShowBView) {
            BView(fruitsName: $fruits.name)
        }
    }
}

struct BView: View {
    @Binding var fruitsName: String
    
    var body: some View {
        Button("みかんに変える") {
            fruitsName = "みかん"
        }
    }
}

まとめ

まとめると、@ObservedObjectというのは、@Published(@Stateのようなもの)をまとめたクラスです。使うときはインスタンス化して使います。

評価