Combine
をSwiftUI TextField
と一緒に使用することで、テキストフィールド TextField
に入力されたコンテンツユーザーに関する更新を取得することができます。
この記事では、以下について説明します。
-
Combine
を使用してTextField
の変更を監視する - ユーザーがテキストフィールドに入力できる文字数の制限
- ユーザーのパスワードに最低限の大文字、記号、数字が含まれているかどうか、更に文字数制限を超えていないかどうかを確認する。
##Combine
を使用してTextField
の変更を監視する
コードは簡単です。まず、Combine
フレームワークをインポートする必要があります。それから .onReceive(Just(messageText))
ビューモディファイアーを TextField
へ追加してください。
完全なコードはこちらです:
import SwiftUI
import Combine
struct ContentView: View {
@State var messageText: String = ""
var body: some View {
Form {
TextField("Message", text: $messageText)
.onReceive(Just(messageText)) { _ in
// テキストを変更する場合にはこちらにコードを入力して下さい
}
.padding()
}
}
}
これで .onReceive
ブロックのコードは、テキストコンテンツが変わる度に呼び出されるようになります。
この記事は、上記のコードを使って追加することができるいくつかの機能性についても解説します。
ユーザーがテキストフィールドに入力できる文字数の制限
ユーザーが SwiftUI TextField
に入力することのできる文字数を制限する場合があります。もしユーザーが制限を超える文字を入力する場合は、余分なテキストを削除することもあります。
import SwiftUI
import Combine
struct ContentView: View {
@State var messageText: String = ""
var body: some View {
Form {
TextField("メッセージ", text: $messageText)
.onReceive(Just(messageText)) { _ in
if messageText.count > 30 {
messageText = String(messageText.prefix(30))
}
}
.padding()
Text(String(messageText.count))
}
}
}
ユーザーに安全なパスワードを選ぶように依頼してください
ユーザーの入力したパスワードが最低でも1つの大文字、1つの記号、数字を含んでいるかどうか、および若干長すぎないかどうか、チェックすることができます。
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-image-store.s3.ap-northeast-1.amazonaws.com%2F0%2F635330%2F94d4b3b8-2455-abf0-d6c0-9472522163a5.gif?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&s=af8a340d1318af93123feedd4a1f9c86)
import SwiftUI
import Combine
struct ContentView: View {
@State var messageText: String = ""
@State var hasCapitalLetter: Bool = false
@State var hasSymbol: Bool = false
@State var lengthExceeds16: Bool = false
var body: some View {
Form {
TextField("メッセージ", text: $messageText)
.onReceive(Just(messageText)) { _ in
self.lengthExceeds16 = (messageText.count > 16)
// 大文字
let capitalLetterExpression = ".*[A-Z]+.*"
let capitalLetterCondition = NSPredicate(format:"SELF MATCHES %@", capitalLetterExpression)
self.hasCapitalLetter = capitalLetterCondition.evaluate(with: messageText)
// 数字: ".*[0-9]+.*"
// 符号
let symbolExpression = ".*[!&^%$#@()/]+.*"
let symbolCondition = NSPredicate(format:"SELF MATCHES %@", symbolExpression)
self.hasSymbol = symbolCondition.evaluate(with: messageText)
}
.padding()
// ユーザーによるパスワード入力をご希望の場合は、`SecureField` をご利用下さい。
Text(String(messageText.count))
.keyboardType(.asciiCapable)
.autocapitalization(.none)
.disableAutocorrection(true)
// パスワード 条件
PasswordConditionDisplay(isConditionMet: $hasCapitalLetter, conditionName: "大文字")
PasswordConditionDisplay(isConditionMet: $hasSymbol, conditionName: "符号")
PasswordConditionDisplay(isConditionMet: $lengthExceeds16, conditionName: "パスワードは16文字を越える必要があります")
}
}
}
struct PasswordConditionDisplay: View {
@Binding var isConditionMet: Bool
var conditionName: String
var body: some View {
HStack {
Image(systemName: isConditionMet ? "circle.fill" : "xmark")
.padding(.horizontal, 5)
Text(conditionName)
}
}
}