如何在附加到 TextField 的 swift @Published didSet 中正确格式化字符串?
Posted
技术标签:
【中文标题】如何在附加到 TextField 的 swift @Published didSet 中正确格式化字符串?【英文标题】:how to properly format string in swift @Published didSet attached to the TextField? 【发布时间】:2020-07-21 07:11:38 【问题描述】:给定一个应该接收电话的TextField,用XX-XX-XXXX模式格式化数字,这个特定的输入字段不允许输入超过8个符号,只能输入字母数字等。 我正在尝试将@ObservableObject 与@Published var 一起使用,但是,当使用后缀更新值时,文本输入位置不会跳转到输入字段的末尾:
class SignupModel: ObservableObject
@Published var phoneNumber: String = ""
didSet
if (self.phoneNumber.count == 3 || self.phoneNumber.count == 5)
if (self.phoneNumber.count == 3)
self.phoneNumber.insert("-", at: String.Index(encodedOffset: 3))
else if self.phoneNumber.count == 5
self.phoneNumber.insert("-", at: String.Index(encodedOffset: 5))
print(self.phoneNumber)
...
@ObservedObject var formModel: SignupModel = SignupModel()
...
TextField("12 3333 123", text: self.$formModel.phoneNumber)
使用 combine 实现验证和格式化的有效方法是什么?
【问题讨论】:
试图这样做,但newValue
似乎是不可变的,并且从willSet
修改phoneNumber
值会产生段错误
【参考方案1】:
我最终实现了didSet
以及一个将选择器放置在输入文本字段末尾的自定义 TextField:
class SignupModel: ObservableObject
@Published var buttonEnabled = false
@Published var phoneNumber: String = ""
didSet
if (self.phoneNumber.count == 13)
phoneNumber = oldValue
self.buttonEnabled = true
return
buttonEnabled = false
if ((self.phoneNumber.count == 2 || self.phoneNumber.count == 5 || self.phoneNumber.count == 8))
if (oldValue.last == " ")
phoneNumber.remove(at: oldValue.index(before: phoneNumber.endIndex))
else
phoneNumber = phoneNumber + " "
下面是来自this 帖子的自定义 TextField 容器:
struct TextFieldContainer: UIViewRepresentable
private var placeholder: String
private var text: Binding<String>
init(_ placeholder: String, text: Binding<String>)
self.placeholder = placeholder
self.text = text
func makeCoordinator() -> TextFieldContainer.Coordinator
Coordinator(self)
func makeUIView(context: UIViewRepresentableContext<TextFieldContainer>) -> UITextField
let innertTextField = UITextField(frame: .zero)
innertTextField.placeholder = placeholder
innertTextField.text = text.wrappedValue
innertTextField.delegate = context.coordinator
context.coordinator.setup(innertTextField)
return innertTextField
func updateUIView(_ uiView: UITextField, context: UIViewRepresentableContext<TextFieldContainer>)
uiView.text = self.text.wrappedValue
class Coordinator: NSObject, UITextFieldDelegate
var parent: TextFieldContainer
init(_ textFieldContainer: TextFieldContainer)
self.parent = textFieldContainer
func setup(_ textField: UITextField)
textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
@objc func textFieldDidChange(_ textField: UITextField)
self.parent.text.wrappedValue = textField.text ?? ""
let newPosition = textField.endOfDocument
textField.selectedTextRange = textField.textRange(from: newPosition, to: newPosition)
我就是这样使用它的:
TextFieldContainer("93 49 99 353", text: self.$formModel.phoneNumber)
【讨论】:
以上是关于如何在附加到 TextField 的 swift @Published didSet 中正确格式化字符串?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中解析到 TextField iOS Keychain?
如何在 Swift 2.0 中使用标签将 TextField 添加到 Cell
Xcode:如何获取 textLabel 以显示在 textField 中输入的附加静态文本?
我如何在SWIFTUI中把textField作为firstResponder,就像Swift一样:textField.becomesFirstResponder。