【SwiftUI】TextFieldをボタンを押すたびに増やす方法!配列でバインディング
この記事からわかること
- Swift UIでボタンを押す度にTextFieldを増やす方法
- TextFieldに配列をバインディングするには?
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
Swift UIでボタンを押す度にTextFieldを増やす機能を実装する方法をまとめました。
TextFieldをボタンを押すたびに増やす
ボタンを押すたびにTextField
を増やすには以下のポイントが重要です。
- TextFieldにバインディングする変数は配列形式
- 配列には空の要素を入れておく
- ボタンを押されるたびに空の要素を増やす
- ForEachで配列個数分繰り返しTextFieldを表示
TextField
構造体を用いる場合は入力値を保持するための変数を用意しなければいけません。ボタンを増やすたびにTextField
が増えていく場合は変数を用意する数もフレキシブルである必要があります。なので配列の中の要素と紐付くようにしていきます。
struct ContentView: View {
@State var memberArray:[String] = [""]
var body: some View {
HStack{
Button(action: {
memberArray.append("")
}, label: {
Image(systemName: "person.fill.badge.plus")
}).foregroundColor(.blue).padding(5)
Button(action: {
memberArray.removeLast()
}, label: {
Image(systemName: "person.fill.badge.minus")
}).foregroundColor(memberArray.count == 1 ? .gray : .red).padding(5).disabled(memberArray.count == 1)
}
ForEach(memberArray.indices, id: \.self) { i in
TextField("メンバー\(i + 1)", text: $memberArray[i]).frame(width: 200).padding(5)
}
}
}
TextFieldの追加はバインディングしている配列内の要素の追加で実装できます。ここではボタンを押されるたびに空の要素をappend
メソッドで追加しています。
memberArray.append("")
Index out of rangeの解決法
TextField構造体を動的に追加/削除することによって注意点があります。それは削除する際に削除対象のTextField構造体にフォーカスが当たっている場合、Index out of range
という致命的なエラーが発生しアプリが停止してしまうことがあります。(明確な発生条件はわかりませんでした。)
これを防ぐには削除前にフォーカスを解除する必要があります。Swift UIではプロパティラッパ@FocusState
とfocused
モディファイアでフォーカスをコントロールできますが、動的に追加する場合、それでは解除することができませんでした。
おすすめ記事:【SwiftUI】@FocusStateとは?複数の入力フォームのフォーカスコントロール
解決策として、Swift UIからあまり操作することはないUIApplication
からresignFirstResponder
メソッドを呼び出すことでフォーカスをリセットしています。
// 削除ボタンの中に記述
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。
私がSwift UI学習に使用した参考書