[SwiftUI] @Binding変数をイニシャライザで受け取った引数で設定するときに気をつけること

SwiftUI

Githubでライブラリを公開しようとしたところ、イニシャライザにもpublicをつける必要がありました。

Structを使っているので、デフォルトでイニシャライザが用意されるのですが、それはどうやら"internal"らしいので、明示的に、定義する必要があります。

普通の引数を受け取るのは、文字通りそのままなのですが、@Bindingの変数を受け取るときに、ハマってしまったので、メモです。

前提

公開しようとしているstructはSelectableListという名前です。structの中に@Binding var selectedItem:T? という変数を持っています。

コード

public struct SelectableList: View {
    @Binding var selectedItem:T?
...

初期値はありませんので、呼び出す側が渡さなければいけないんですが、呼び出し側からは以下のように使います。

コード

@State private var selection:T?
...
SelectableList(selectedItem: $selection)

普通に呼び出せています。今回、publicなイニシャライザを定義しなければいけないので、これまで自動で良いされていたイニシャライザを
自分で記述しなければいけなくなりました。

直感的(?)に書くとエラー

他のタイプの変数と同様に以下のコードを書くと、エラーになります。

コード

public struct SelectableList: View {
    @Binding var selectedItem:T?
    public init(selectedItem: Binding) {   // 
       self.selectedItem = selectedItem        // <- 追加したイニシャライザ
    }                                          //
...

エラーは、"Cannot assign value of type 'Binding<T?>' to type 'T'"です。

@Binding変数をイニシャライザの引数で受け取るとき

Googleしてもあまりヒットせず、ずっと悩んだのですが、正解は、以下でした。

コード

public struct SelectableList: View {
    @Binding var selectedItem:T?
    public init(selectedItem: Binding) {   // 
       self._selectedItem = selectedItem
    }
...

@Bindingは、PropertyWrapperなので、実際には、_変数 で保持されているということでした。wrapper経由で設定してしまうと、不要なコードが動き始めるんでしょうね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です