我正在尝试使用模式或掩码格式化 SwiftUI TextField 中的数据。(为清楚起见 - 不是 UITextField)。一个例子是美国的电话号码。因此,用户可以键入 1115551212,视图中的结果为 111-555-1212。在这种情况下,我将使用数字键盘,但为了将来,使用全键盘,如果用户键入非数字,我希望能够用某些内容替换它,例如 0。因此输入 111abc1212 将导致111-000-1212。尽管下面的代码将字符串转换为数字,但理想情况下,我希望掩码对字符串而不是数字进行操作 - 从而可以灵活地格式化零件编号等。
我已经能够使用通过按钮操作的函数来做到这一点,但当然我希望它是自动的。我使用 SwiftUI 修饰符来完成同样的事情完全不成功。在我的测试中,使用内置的 .textContentType(.telephoneNumber) 绝对没有任何作用。
我希望有一些像 .onExitCommand 这样的修饰符可以在焦点离开 TextField 时执行,但我没有看到解决方案。
此代码适用于该按钮(稍后我将添加规则以在需要数字时过滤数字):
struct ContentView: View {
@State private var phoneNumber = ""
@State private var digitArray = [1]
var body: some View {
VStack {
Group {//group one
Text("Phone Number with Format").font(.title)
.padding(.top, 40)
TextField("enter phone number", text: $phoneNumber)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
.keyboardType(.numberPad)
}//Group one
Group {//group two
Button(action: {self.populateTextFieldWithPhoneFormat(phoneString: self.phoneNumber)}) {
Text("Convert to Phone Format")
}
}//group two
Spacer()
}//VStack
}
func populateTextFieldWithPhoneFormat(phoneString: String) {
var digitArray = [Int]()
let padded = phoneNumber.padding(toLength: 10, withPad: "0", startingAt: 0)
let paddedArray = padded.map {String($0)}
for char in paddedArray {
digitArray.append(Int(char) ?? 0)
}
phoneNumber = format(digits: digitArray)
}//populate
func format(digits: [Int]) -> String {
var phone = digits.map(String.init)
.joined()
if digits.count > 3 {
phone.insert("-", at: phone.index(
phone.startIndex,
offsetBy: 3)
)
}
if digits.count > 7 {
phone.insert("-", at: phone.index(
phone.startIndex,
offsetBy: 7)
)
}
return phone
}
}
Run Code Online (Sandbox Code Playgroud)
我也尝试制作自己的 ViewModifier,但一事无成。
Xcode 版本 11.2.1 (11B500)
SwiftUI 上的 TextField 有一些有趣的重载,可以轻松解决您的问题。我设法为 MAC 地址格式化程序制作了一个 TextField 掩码,如下所示(##:##:##:##:##)。下面是一个简单的代码片段,可以实现这个目的:
class MacAddressFormatter: Formatter {
override func string(for obj: Any?) -> String? {
if let string = obj as? String {
return formattedAddress(mac: string)
}
return nil
}
override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
obj?.pointee = string as AnyObject?
return true
}
func formattedAddress(mac: String?) -> String? {
guard let number = mac else { return nil }
let mask = "##:##:##"
var result = ""
var index = number.startIndex
for ch in mask where index < number.endIndex {
if ch == "#" {
result.append(number[index])
index = number.index(after: index)
} else {
result.append(ch)
}
}
return result
}
}
Run Code Online (Sandbox Code Playgroud)
在您的情况下,您应该更改formattedAddress(mac: String) -> String?方法以便根据需要返回结果。
下面是上述内容的简单 SwiftUI 实现:
struct ContentView: View {
@State private var textFieldValue:String = ""
var body: some View {
NavigationView {
List {
TextField("First 6 bytes", value: $textFieldValue, formatter: MacAddressFormatter())
}
.navigationBarTitle("Mac Lookup", displayMode: .inline)
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于更好奇的人: 在这里您可以找到一篇关于这个主题的非常有趣的文章。
| 归档时间: |
|
| 查看次数: |
7280 次 |
| 最近记录: |