Help us understand the problem. What is going on with this article?

SwiftUI で @State の初期状態を外から受け取る

@State private var の場合

例えば、テキストを編集するための View について考えてみましょう。

  1. 前画面から既存の文字列を受け取り、 TextField の初期値として表示する
  2. 表示された文字列を修正することができる

このような仕様の場合、 1 は以下のようなコードで実現できます。

struct TextEditView: View {
    @State private var text: String

    init(text currentText: String) {
        _text = State(initialValue: currentText)
    }

    var body: some View {
        TextField("", text: $text)
    }
    ...
}

let currentText = "Today was a good day."
TextEditView(text: currentText)

あれ?こっちは??

struct TextEditView: View {
    @State private var text: String

    init(text currentText: String) {
        text = currentText    // ❗️ Return from initializer without initializing all stored properties
    }
    ...
}

初期化が完了していないというエラーが出ます。text に代入してるのに。。

実は初期化する必要があるのは、

文字列 ではなく 文字列の状態
String ではなく State<String>
text ではなく _text 1

です。 text の 初期状態 をセットしてあげる必要があります。
(初期値ではなく、初期状態と表現する方が適切かと思います。)

今回の例では currentText: StringState でラップし 状態 として代入しています。

_text = State(initialValue: currentText)

@State var の場合

こちらは素直にコンパイルが通ります。

struct TextEditView: View {
    @State var text: String
    ...
}

let currentText = "Today was a good day."
TextEditView(text: currentText)

イニシャライザが内部でうまく処理してくれてるのかな。


  1. _ (アンダースコア) を付けることで Property Wrapper 自身にアクセスできる。 

muhiro12
iOS Developerでありたい / Androidもまぁできる / Flutterたのしい / フリーランス
https://note.com/muhiro12
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away