ひとしれずひっそり

主にソフトに関することをメモしていきます。過程をそのまま書いていたりするので間違いが含まれます。鵜呑みしない様に。

TextField

TextFieldで編集が終わったら値をセットする方法。

Optionalを扱うモデルを用意してBindするところまで。
OptionalだとTextFieldにBindingできないのでView内のメンバnameで一旦受ける。
onAppearのタイミングでセットする。

import SwiftUI

// CoreDataを想定してOptionalを扱うモデルを用意
struct Person {
    var name: String? = nil
}

struct ContentView: View {
    @State var person = Person()
    @State var name: String = ""
    var body: some View {
        VStack {
            TextField("Name", text: $name)
        }
        .padding()
        .onAppear() {
            // Optionalの値は一旦nameに置換える
            name = person.name ?? ""
        }
    }
}

struct ContentView_Previews:
    PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

ここまでのソース

TextViewについて · GitHub


編集が終わったらモデルにセットする様にするにはonEditingChangedを使用する。

            TextField("Name", text: $name, onEditingChanged: <#T##(Bool) -> Void#>

<#T##(Bool) -> Void#>を選択してリターンキーを押すとonEditingChangedはBlockに展開された。

            TextField("Name", text: $name) { editing in
                if editing == false {
                    person.name = name
                }
            }

空文字の場合はモデルにセットしない様にするには

            TextField("Name", text: $name) { editing in
                if editing == false {
                    if isValid {
                        person.name = name
                    }
                }
            }
 .
 .
    }
    
    private var isValid: Bool {
        return !name.isEmpty
    }

ここまでのソース

TextViewについて · GitHub


有効な名前がセットされるまでフォーカスを抜けたくない場合focusedを使う。
isFocused を true にするとフォーカスを戻す事ができる。

    @FocusState var isFocused: Bool
    var body: some View {
        VStack {
            TextField("Name", text: $name) { editing in
                if editing == false {
                    if isValid {
                        person.name = name
                    } else {
                        isFocused = true
                    }
                }
            }
            .focused($isFocused)
        }

ここまでのソース

TextViewについて · GitHub


無効な名前の場合警告として背景を赤色にするにはbackgroundで設定する。
onChangeを使わなくてもnameが更新されてViewが更新される様だ。

    let invalidColor = Color(red: 1.0, green: 0.7, blue: 0.7)
    var body: some View {
        VStack {
            TextField("Name", text: $name) { editing in
                if editing == false {
                    if isValid {
                        person.name = name
                    } else {
                        isFocused = true
                    }
                }
            }
            .focused($isFocused)
            .background(RoundedRectangle(cornerRadius: 2).fill(isValid ? .clear : invalidColor))

ここまでのソース

TextViewについて · GitHub

つづきを書いた

katsuyoshi.hatenadiary.com