【SwiftUI】Bindingを@Bindingに代入する

はじめに

@Binding var isPresented: Bool のようなプロパティを、カスタムイニシャライザなどで引数渡しで初期化する場合は・・・

struct SubView: View {

    @Binding var isPresented: Bool
    
    init(isPresented: Binding<Bool>) {
        self._isPresented = isPresented
    }


こう!

引数の型はBinding<Bool>で、プロパティに代入するには名前の前にアンダースコア(_)を付ける!

以上、今回の結論になります。

なぜこれを書いたか?

sheetを使ったModal Viewの表示処理を書いていて、Modalを閉じる処理のためModal View側に呼び出し側の「@State var isPresented: Bool = false」なプロパティを受け取る「@Binding var isPresented: Bool」プロパティを書いたまでは良かったけど、Modal Viewにカスタムイニシャライザを設ける必要があって、明示的に引数を使ってisPresentedを初期化しなきゃいけなくなり、単に「self.isPresented = isPresented」と書いたらコンパイラさんに怒られたため、じゃあどうすんだべと思って調べたらけっこう見つからなくて苦労したので、これは書いておいた方がいいかなと思った次第です。
(長い)

サンプルコード

要はこんな感じというサンプルを載せます。

Xcode 11.3.1 にて作成&動作確認。

// メインView
struct ContentView: View {
    
    @State var isPresented: Bool = false
    
    var body: some View {
        VStack(alignment: .center, spacing: 16) {
            Text("ContentView")

            Button(action: {
                
                self.isPresented = true
                
            }) {
                Text("Show SubView")
            }
        }
        .sheet(isPresented: self.$isPresented) {
            SubView(isPresented: self.$isPresented)
        }
    }
}

// サブView。メインから表示される
struct SubView: View {

    @Binding var isPresented: Bool
    
    init(isPresented: Binding<Bool>) {
        self._isPresented = isPresented
    }

    var body: some View {
        VStack(alignment: .center, spacing: 16) {
            Text("SubView")
            
            Button(action: {
                
                self.isPresented = false

            }) {
                Text("Dismiss SubView")
            }
        }
    }
}

sheetの使い方は多くのサイトで紹介されているので、特に解説は省きたいと思います。

おわりに

SwiftUIも一見簡単なようで、やり込んでいくとちょいちょいこうした細かい問題に引っかかりますね。
Appleのドキュメントやサンプルコードがどれもシンプルすぎて困ります。

はい。

この記事が、同じくこの問題に行き当たった人の助けになれば幸いです。