我有一个简单的TextField用于电话输入,并且想在每次更改时对其进行格式化。
我正在使用PhoneNumberKit,它工作正常,但是在textField中的值更改后,我不明白如何调用格式化函数。
电话格式化功能。
import SwiftUI
import PhoneNumberKit
import Combine
func formatTelephone(telephone : String) -> String
{
do {
let phoneNumber = PartialFormatter().formatPartial(telephone)
print(phoneNumber)
return phoneNumber
}
catch {
print("Generic parser error")
}
}
它执行以下操作:
formatTelephone("79152140700") -> "7 (915) 214 08-00"
formatTelephone("791521") -> "7 (915) 21"
我有一个像这样的TextField
TextField("915 214 07 00" , text: $telephoneManager.telephone)
每次输入数字后,整个文本字段标签都需要用func格式化,并以更好的方式显示用户的输入。
答案 0 :(得分:0)
为了获得想要的东西,您需要使用Combine(视图模型中两种方法的实现完全取决于您,因为它们严格取决于您的需求):
import SwiftUI
import Combine
class ContentViewModel: ObservableObject {
@Published var phoneNumber = ""
private var toCancel: AnyCancellable!
init() {
toCancel = $phoneNumber
.filter { !self.isFormatValid($0) }
.map { self.convert($0) }
.receive(on: RunLoop.main)
.assign(to: \.phoneNumber, on: self)
}
private func isFormatValid(_ str: String) -> Bool {
//here you must check if _str_ is already in the right format
true //just to make this example compile, but clearly this must be replaced with your code
}
private func convert(_ str: String) -> String {
//convert your string to be in the right format
"string in the correct format" //just to make this example compile, but clearly this must be replaced with your code
}
deinit {
toCancel.cancel()
}
}
struct ContentView: View {
@ObservedObject var contentViewModel = ContentViewModel()
var body: some View {
TextField("Your phone number...", text: $contentViewModel.phoneNumber)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
步骤如下(查看视图模型的初始化):
phoneNumber
是@Published
的属性,因此可以由订阅的发布者“支持”。因此,让我们订阅该发布者。.filter
运算符完成的。仅当.filter
运算符返回true时才向下转发事件(在这种情况下,如果字符串格式无效,则返回true)。.map
运算符,您可以更改字符串(格式错误)并以正确的格式返回字符串。.receive
可让您在感兴趣的线程上转发事件。在这种情况下,主线程(因为您要更新文本字段)。.assign
只是将新值分配给文本字段。