はじめに
SwiftUIのTextFieldの実装方法についてドキュメントを読んで調べてみました。
(ついでにTextEditor、SecureFieldも)
環境
Xcode 13.4.1
内容
- TextField
- TextEditor
- SecureField
TextField
編集可能なテキストインターフェイスを表示
struct TextField<Label> where Label : View
ラベルと値へのバインドを持つテキストフィールドを作成する。値が文字列の場合、ユーザーがフィールド内のテキストを入力または編集すると、テキストフィールドはこの値を継続的に更新、文字列でない場合は、ユーザーがReturnキーを押すなどして編集をコミットすると値が更新される
@State private var username: String = ""
@FocusState private var emailFieldIsFocused: Bool
var body: some View {
TextField(
"User name (email address)",
text: $username
)
.focused($emailFieldIsFocused)
.onSubmit {
// validate(name: username)
}
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
.border(.secondary)
Text(username)
.foregroundColor(emailFieldIsFocused ? .red : .blue)
}
さらに、FormatStyle
を使用すると、テキストフィールドを非文字列型にバインドし、入力されたテキストをバインドされた型のインスタンスに変換することができる。
例えば、PersonNameComponents.FormatStyle
を使用して、テキスト フィールドに入力された名前を PersonNameComponents
インスタンスに変換するなど
@State private var nameComponents = PersonNameComponents()
var body: some View {
TextField(
"Proper name",
value: $nameComponents,
format: .name(style: .medium)
)
.onSubmit {
// validate(components: nameComponents)
}
.disableAutocorrection(true)
.border(.secondary)
Text(nameComponents.debugDescription)
}
TextField
のスタイル設定
TextFieldStyle
のインスタンスを渡してtextFieldStyle(_:)
を使えば、外観や動作をカスタマイズすることができる
@State private var givenName: String = ""
@State private var familyName: String = ""
var body: some View {
VStack {
TextField(
"Given Name",
text: $givenName
)
.disableAutocorrection(true)
TextField(
"Family Name",
text: $familyName
)
.disableAutocorrection(true)
}
.textFieldStyle(.roundedBorder)
}
TextEditor
長文テキストを表示・編集することができる
struct TextEditor
テキストエディタViewを使用すると、アプリのユーザーインターフェイスに複数行のスクロール可能なテキストを表示したり編集したりすることができる
@State private var fullText: String = "This is some editable text..."
var body: some View {
TextEditor(text: $fullText)
.foregroundColor(Color.gray)
.font(.custom("HelveticaNeue", size: 13))
.lineSpacing(5)
}

SecureField
TextField
と同様の動作をさせたいが、ユーザーのテキストは表示したくない(パスワードなどの機密情報)場合に使用
struct SecureField<Label> where Label : View
SecureField
では、文字列値へのバインドと、ユーザがReturnキーを押すなどして編集をコミットしたときに実行されるクロージャが使用される。フィールドは、キーストロークなどの編集のたびにバインドされた文字列を更新するので、Doneボタンなどの他のコントロールからいつでもその値を読み取ることができる
@State private var username: String = ""
@State private var password: String = ""
var body: some View {
TextField(
"User name (email address)",
text: $username)
.autocapitalization(.none)
.disableAutocorrection(true)
.border(Color(UIColor.separator))
SecureField(
"Password",
text: $password
) {
// handleLogin(username: username, password: password)
}
.border(Color(UIColor.separator))
}
おまけ
ここからはドキュメントの内容から少し離れます。。。
改行のできるTextField
を作成する
こちらはiOS16から使用でき、まだ現状はベータ版のようですが
TextField
だけで改行ができ、さらに行数を指定することで枠の最大も決められて便利そう
@State private var text: String = ""
var body: some View {
TextField("Title", text: $text, axis: .vertical)
.lineLimit(0...10)
.border(.secondary)
}
TextField
は使わず、TextEditor
を使う
iOS15ではTextField
を使うと改行ができないので、
TextEditor
を使って実現します
@State private var text: String = ""
var body: some View {
List {
Text("Enter the message")
ZStack {
TextEditor(text: $text)
Text(text).opacity(0).padding(.all, 8)
}
.shadow(radius: 1)
}
.listStyle(.plain)
}


おわりに
iOS16からはTextField
で改行ができるようになるので、メッセージやコメント機能がより簡単に実装できそうでとても良さそうです🙌
参考