しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

SwiftUIのEnvironment/EnvironmentObjectとはなにか

SwiftUIのEnvironment / EnvironmentObjectという記法について調べてみました。

EnvironmentObjectとは

EnvironmentObjectとはObservableObjectを外部から渡したりできるようになる記法です。
宣言は下のように行います。

struct ContentView: View {
    @EnvironmentObject var testValue: MyViewModel
    
    var body: some View {
        Text("Hello")
    }
}

class MyViewModel: ObservableObject {
}

プロパティーの型はObservableObjectプロトコルに準拠している必要があります。
また、通常のプロパティーと違って初期値をセットする必要はありません。

@EnvironmentObject var testValue: MyViewModel

EnvironmentObjectの値は、下のようにenvironmentObjectメソッドで外部から注入することができます。

let contentView = ContentView().environmentObject(MyViewModel())

通常のプロパティー同様、値を以下のように取得することができます。

struct ContentView: View {
    @EnvironmentObject var testValue: MyViewModel
    
    var body: some View {
        print(testValue)
        return Text("Hello")
    }
}

MyViewModelのプロパティーを2つ宣言すると、両方に同じ値がセットされます。

struct ContentView: View {
    @EnvironmentObject var testValue: MyViewModel
    @EnvironmentObject var testValue2: MyViewModel
    
    var body: some View {
        print(testValue === testValue2) // → true
        return Text("Hello")
    }
}

environmentObjectでセットした値は、子ビューにも自動でセットされます。

struct ContentView: View {
    @EnvironmentObject var testValue: MyViewModel
    
    var body: some View {
        ChildView()
    }
}

struct ChildView: View {
    @EnvironmentObject var testValue: MyViewModel
    
    var body: some View {
        print(testValue) // 値が入っている
        return Text("Hello, World!")
    }
}

Environmentとは

EnvironmentもEnvironmentObjectと似て、外部から値をセットできるようになるクラスです。
下のようにenvironmentメソッドを使って値をセットできます。

let contentView = ContentView().environment(\.font, Font.system(size: 100))

ここでセットできるのは、fontなどEnvironmentValuesのプロパティーとして宣言されているものだけです。
詳細は以下URLに参考にしてください。

https://developer.apple.com/documentation/swiftui/environmentvalues

フォントをセットした場合、以下のようにTextのデフォルトフォントサイズが変更されます。

f:id:llcc:20200308204035p:plain

セットした値にアクセスするためには、以下のようにEnvironmentを使ってプロパティーを宣言する必要があります。

struct ContentView: View {
    @Environment(\.font) var myFont: Font?
    
    var body: some View {
        print(myFont)
        return Text("Hello")
    }
}

参考URL

SwiftUIの機能 @State, @ObservedObject, @EnvironmentObjectの違いとは| 開発者ブログ | 株式会社アイソルート

Understanding Property Wrappers in SwiftUI | Majid’s blog about Swift development