Enable/Disable 按钮,用于验证在文本字段中输入的 phone 数字
Enable/Disable button with validating phone number entered in a textfield
作为一个整体,我对 ReactiveSwift 和 MVVM 非常陌生。我正在尝试根据验证结果验证 phone 输入到文本字段中的数字和 enable/disable 按钮。
在应用程序中,有一个文本字段和一个名为“提交”的 UIButton
按钮。对于 phone 号码验证,我使用了一个名为 [PhoneNumberKit][1]
的开源库。它还提供了一个 UITextField
子类,用于格式化用户输入。
我混合了一个看起来像这样的解决方案。
class ViewController: UIViewController {
@IBOutlet weak var textField: PhoneNumberTextField!
@IBOutlet weak var submitButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
submitButton.isEnabled = false
let textValuesSignal = textField.reactive.continuousTextValues
SignalProducer(textValuesSignal).start { result in
switch result {
case .value(let value):
print(value)
self.submitButton.isEnabled = self.isPhoneNumberValid(value)
case .failed(let error):
print(error)
self.submitButton.isEnabled = false
case .interrupted:
print("inturrupted")
self.submitButton.isEnabled = false
case .completed:
print("completed")
}
}
}
func isPhoneNumberValid(_ phoneNumberString: String) -> Bool {
do {
let phoneNumber = try PhoneNumberKit().parse(phoneNumberString)
let formattedPhoneNumber = PhoneNumberKit().format(phoneNumber, toType: .e164)
print("Phone number is valid: \(formattedPhoneNumber)")
return true
} catch let error {
print("Invalid phone number: \(error)")
return false
}
}
}
这样就可以了,但不是很优雅。此外,用户输入与 UI 更改之间存在显着滞后。
另一件事是我上面的解决方案不符合 MVVM。我又试了一次。
class ViewController: UIViewController {
@IBOutlet weak var textField: PhoneNumberTextField!
@IBOutlet weak var submitButton: UIButton!
private let viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
submitButton.reactive.isEnabled <~ viewModel.isPhoneNumberValid
viewModel.phoneNumber <~ textField.reactive.continuousTextValues
}
}
class ViewModel {
let phoneNumber = MutableProperty("")
let isPhoneNumberValid = MutableProperty(false)
init() {
isPhoneNumberValid = phoneNumber.producer.map { self.validatePhoneNumber([=13=]) } // Cannot assign value of type 'SignalProducer<Bool, NoError>' to type 'MutableProperty<Bool>'
}
private func validatePhoneNumber(_ phoneNumberString: String) -> Bool {
do {
let phoneNumber = try PhoneNumberKit().parse(phoneNumberString)
let formattedPhoneNumber = PhoneNumberKit().format(phoneNumber, toType: .e164)
print("Phone number is valid: \(formattedPhoneNumber)")
return true
} catch let error {
print("Invalid phone number: \(error)")
return false
}
}
}
当我将 validatePhoneNumber
函数的结果分配给 isPhoneNumberValid
属性.
时,初始化程序出现以下错误
Cannot assign value of type 'SignalProducer' to type 'MutableProperty'
我不知道如何将 phone 数字验证部分与提交按钮的 isEnabled
属性 和点击操作正确连接起来。
尝试在 init
中设置 属性 并映射 属性 本身而不是生产者:
let isPhoneNumberValid: Property<Bool>
init() {
isPhoneNumberValid = phoneNumber.map { ViewModel.validatePhoneNumber([=10=]) }
}
您必须将 validatePhoneNumber
设为静态方法,因为 self
尚不可用。
这是一种更典型的反应式方法,因为您在视图模型初始化期间完全根据另一个定义了一个 属性。
作为一个整体,我对 ReactiveSwift 和 MVVM 非常陌生。我正在尝试根据验证结果验证 phone 输入到文本字段中的数字和 enable/disable 按钮。
在应用程序中,有一个文本字段和一个名为“提交”的 UIButton
按钮。对于 phone 号码验证,我使用了一个名为 [PhoneNumberKit][1]
的开源库。它还提供了一个 UITextField
子类,用于格式化用户输入。
我混合了一个看起来像这样的解决方案。
class ViewController: UIViewController {
@IBOutlet weak var textField: PhoneNumberTextField!
@IBOutlet weak var submitButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
submitButton.isEnabled = false
let textValuesSignal = textField.reactive.continuousTextValues
SignalProducer(textValuesSignal).start { result in
switch result {
case .value(let value):
print(value)
self.submitButton.isEnabled = self.isPhoneNumberValid(value)
case .failed(let error):
print(error)
self.submitButton.isEnabled = false
case .interrupted:
print("inturrupted")
self.submitButton.isEnabled = false
case .completed:
print("completed")
}
}
}
func isPhoneNumberValid(_ phoneNumberString: String) -> Bool {
do {
let phoneNumber = try PhoneNumberKit().parse(phoneNumberString)
let formattedPhoneNumber = PhoneNumberKit().format(phoneNumber, toType: .e164)
print("Phone number is valid: \(formattedPhoneNumber)")
return true
} catch let error {
print("Invalid phone number: \(error)")
return false
}
}
}
这样就可以了,但不是很优雅。此外,用户输入与 UI 更改之间存在显着滞后。
另一件事是我上面的解决方案不符合 MVVM。我又试了一次。
class ViewController: UIViewController {
@IBOutlet weak var textField: PhoneNumberTextField!
@IBOutlet weak var submitButton: UIButton!
private let viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
textField.becomeFirstResponder()
submitButton.reactive.isEnabled <~ viewModel.isPhoneNumberValid
viewModel.phoneNumber <~ textField.reactive.continuousTextValues
}
}
class ViewModel {
let phoneNumber = MutableProperty("")
let isPhoneNumberValid = MutableProperty(false)
init() {
isPhoneNumberValid = phoneNumber.producer.map { self.validatePhoneNumber([=13=]) } // Cannot assign value of type 'SignalProducer<Bool, NoError>' to type 'MutableProperty<Bool>'
}
private func validatePhoneNumber(_ phoneNumberString: String) -> Bool {
do {
let phoneNumber = try PhoneNumberKit().parse(phoneNumberString)
let formattedPhoneNumber = PhoneNumberKit().format(phoneNumber, toType: .e164)
print("Phone number is valid: \(formattedPhoneNumber)")
return true
} catch let error {
print("Invalid phone number: \(error)")
return false
}
}
}
当我将 validatePhoneNumber
函数的结果分配给 isPhoneNumberValid
属性.
Cannot assign value of type 'SignalProducer' to type 'MutableProperty'
我不知道如何将 phone 数字验证部分与提交按钮的 isEnabled
属性 和点击操作正确连接起来。
尝试在 init
中设置 属性 并映射 属性 本身而不是生产者:
let isPhoneNumberValid: Property<Bool>
init() {
isPhoneNumberValid = phoneNumber.map { ViewModel.validatePhoneNumber([=10=]) }
}
您必须将 validatePhoneNumber
设为静态方法,因为 self
尚不可用。
这是一种更典型的反应式方法,因为您在视图模型初始化期间完全根据另一个定义了一个 属性。