我正在尝试使用模式或掩码在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
}
}
我也尝试制作自己的ViewModifier,但是一无所获。
任何指导将不胜感激。
Xcode版本11.2.1(11B500)
答案 0 :(得分:1)
这不是您要查找的构造函数吗?
/// Creates an instance with a `Text` label generated from a title string.
///
/// - Parameters:
/// - title: The title of `self`, describing its purpose.
/// - text: The text to be displayed and edited.
/// - onEditingChanged: An `Action` that will be called when the user
/// begins editing `text` and after the user finishes editing `text`,
/// passing a `Bool` indicating whether `self` is currently being edited
/// or not.
/// - onCommit: The action to perform when the user performs an action
/// (usually the return key) while the `TextField` has focus.
public init<S>(_ title: S, text: Binding<String>,
onEditingChanged: @escaping (Bool) -> Void = { _ in },
onCommit: @escaping () -> Void = {}) where S : StringProtocol
答案 1 :(得分:1)
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
}
}
在您的情况下,您应该更改 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)
}
}
}
对于更好奇的人: Here 您可以找到有关此主题的非常有趣的文章。