如何让 SwiftUI TextField 显示数字但也接受空值
How to get SwiftUI TextField to show numbers but also accept an empty value
我正在尝试获取一个仅接受数字但也接受空值的文本字段(即它是一个可选字段)。这是文本字段的样子:
TextField("Phone Number", value: $phoneNumber, formatter: numberFormatter)
.disableAutocorrection(true)
.autocapitalization(.none)
我的数字格式化程序如下所示:
@State private var numberFormatter: NumberFormatter = {
var nf = NumberFormatter()
nf.numberStyle = .none
nf.zeroSymbol = ""
return nf
}()
我尝试了两种不同的解决方案,但都存在问题。第一个解决方案是将 phoneNumber
定义为可选整数 Int?
以便 TextField
将接受空白输入:
@State var phoneNumber: Int? = nil
然而,这与 TextField
混淆,因此当我通过应用程序更改其值时,更改不会更新实际变量 phoneNumber
。所以,当我去发送我的数据时,phoneNumber
仍然停留在 nil
。我认为这与 numberFormatter
以及它如何不接受 nil
变量有关。
因此,我的第二个解决方案是将 phoneNumber
初始化为 Int
,如下所示:
@State var phoneNumber: Int = 0
当我更改 TextField
中的文本时,此解决方案会更新 phoneNumber
。但是,当我输入 0 时,它只会在 TextField
框中显示空白 space(因为我在 numberFormatter
中定义了 .zeroSymbol
)。当我尝试只输入一个空白 space(即删除所有文本)然后单击 TextField
之外时,它只是恢复到之前的数字。当我在字段中输入一个非数字条目时,也会发生同样的事情,我可以接受,因为它应该只接受数字,但我仍然希望允许用户包含一个空白条目。
我正在使用 XCode 并创建一个 iOS 应用程序。感谢您的帮助。
一个可能的解决方案是通过代理绑定拦截 input/output 并执行所需的额外 validation/processing。
测试 Xcode 13.3 / iOS 15.4
这是主要部分:
TextField("Phone Number", value: Binding(
get: { phoneNumber ?? 0},
set: { phoneNumber = phoneNumber == [=10=] ? nil : [=10=] }
), formatter: numberFormatter)
我找到的另一个解决方案是将 phoneNumber
设为默认为 ""
的字符串。然后,通过 Int(phoneNumber)
尝试将其转换为 Int
来验证它。如果 Int(phoneNumber) == nil
,则引发错误。否则,您现在有一个新的可选整数,可以是 nil 或提供的整数:
var intPhoneNumber: Int?
if phoneNumber == "" {
intPhoneNumber = nil
} else {
intPhoneNumber = Int(phoneNumber)
if intPhoneNumber == nil {
completion(.failure(.custom(errorMessage: "Please enter a valid phone number. Try again.")))
return
} else if intPhoneNumber! < 0 {
completion(.failure(.custom(errorMessage: "Invalid Phone Number. Please enter a valid 10 digit phone number.")))
return
} else if numberOfDigits(in: intPhoneNumber!) != 10 {
completion(.failure(.custom(errorMessage: "Invalid Phone Number. Please enter a valid 10 digit phone number.")))
return
}
}
我正在尝试获取一个仅接受数字但也接受空值的文本字段(即它是一个可选字段)。这是文本字段的样子:
TextField("Phone Number", value: $phoneNumber, formatter: numberFormatter)
.disableAutocorrection(true)
.autocapitalization(.none)
我的数字格式化程序如下所示:
@State private var numberFormatter: NumberFormatter = {
var nf = NumberFormatter()
nf.numberStyle = .none
nf.zeroSymbol = ""
return nf
}()
我尝试了两种不同的解决方案,但都存在问题。第一个解决方案是将 phoneNumber
定义为可选整数 Int?
以便 TextField
将接受空白输入:
@State var phoneNumber: Int? = nil
然而,这与 TextField
混淆,因此当我通过应用程序更改其值时,更改不会更新实际变量 phoneNumber
。所以,当我去发送我的数据时,phoneNumber
仍然停留在 nil
。我认为这与 numberFormatter
以及它如何不接受 nil
变量有关。
因此,我的第二个解决方案是将 phoneNumber
初始化为 Int
,如下所示:
@State var phoneNumber: Int = 0
当我更改 TextField
中的文本时,此解决方案会更新 phoneNumber
。但是,当我输入 0 时,它只会在 TextField
框中显示空白 space(因为我在 numberFormatter
中定义了 .zeroSymbol
)。当我尝试只输入一个空白 space(即删除所有文本)然后单击 TextField
之外时,它只是恢复到之前的数字。当我在字段中输入一个非数字条目时,也会发生同样的事情,我可以接受,因为它应该只接受数字,但我仍然希望允许用户包含一个空白条目。
我正在使用 XCode 并创建一个 iOS 应用程序。感谢您的帮助。
一个可能的解决方案是通过代理绑定拦截 input/output 并执行所需的额外 validation/processing。
测试 Xcode 13.3 / iOS 15.4
这是主要部分:
TextField("Phone Number", value: Binding(
get: { phoneNumber ?? 0},
set: { phoneNumber = phoneNumber == [=10=] ? nil : [=10=] }
), formatter: numberFormatter)
我找到的另一个解决方案是将 phoneNumber
设为默认为 ""
的字符串。然后,通过 Int(phoneNumber)
尝试将其转换为 Int
来验证它。如果 Int(phoneNumber) == nil
,则引发错误。否则,您现在有一个新的可选整数,可以是 nil 或提供的整数:
var intPhoneNumber: Int?
if phoneNumber == "" {
intPhoneNumber = nil
} else {
intPhoneNumber = Int(phoneNumber)
if intPhoneNumber == nil {
completion(.failure(.custom(errorMessage: "Please enter a valid phone number. Try again.")))
return
} else if intPhoneNumber! < 0 {
completion(.failure(.custom(errorMessage: "Invalid Phone Number. Please enter a valid 10 digit phone number.")))
return
} else if numberOfDigits(in: intPhoneNumber!) != 10 {
completion(.failure(.custom(errorMessage: "Invalid Phone Number. Please enter a valid 10 digit phone number.")))
return
}
}