92122


swift ui で

TextEditorをインスタンス化しようとすると

Cannot use instance member '$text' within property initializer; property
initializers run before 'self' is available

というアラートが出ます。

let textEditor = TextEditor(text: $text)

としています。


CC BY-SA 4.0
2022-11-10T00:45:17.863
92116
2022-11-10T03:31:59.903
39481
question
swift
swift ui アラート Cannot use instance member '$text' within property initializer; property initializers run before 'self' is available


いくつか問題があるので、上げていきます。

  1. Stored Propertyでは宣言時に他のPropertyは使えない
  2. SwiftUIにてViewは基本的に変数にしない

おそらくこのようなコードになっていると思います。

[code]

    struct ContentView: View {
      @State var text: String = "Hello"
      
      let textEditor = TextEditor(text: $text) // Cannot use instance member '$text' within property initializer; property initializers run before 'self' is available
      
      var body: some View {
        textEditor
      }
    }
    
[/code]

## 問題1: 解決方法

Computed Propertyにする

[code]

    struct ContentView: View {
      @State var text: String = "Hello"
      
      var textEditor: TextEditor { TextEditor(text: $text) }
      
      var body: some View {
        textEditor
      }
    }
    
[/code]

## 問題2: Viewを変数にしない

これは流派とか考え方の一例なので絶対ではありません。

Viewを切り出したい時、変数化、struct化を選ぶときの基準は、Previewするほどかという点です。  
Previewが必要ないのであればstructを選びましょう。

以下が参考になります。

<https://speakerdeck.com/uhooi/iosdc-japan-2022>

## 自分だったら

もしTextEditorを比較的複雑なカスタマイズをするのであれば別structに切り出します。

そうでなければbody内で直接使います。

### 例1

[code]

    struct ContentView: View {
      @State var text: String = "Hello"
      
      var body: some View {
        TextEditor(text: $text)
      }
    }
    
[/code]

### 例2

[code]

    struct ContentView: View {
      @State var text: String = "Hello"
      
      var body: some View {
        VStack {
          RichTextEditor(text: $text)
        }
      }
    }
    
    struct RichTextEditor: View {
      @Binding var text: String
      
      var body: some View {
        VStack {
          Text("Editor")
            .padding()
            .border(.blue)
            .padding()
          
          TextEditor(text: $text)
        }
        .border(.red, width: 5)
      }
    }
    
[/code]


CC BY-SA 4.0
2022-11-10T03:31:59.903
92122
2022-11-10T03:31:59.903
40856
92116
answer