SwiftUI 结合 ViewModel 电子邮件验证
SwiftUI Combine ViewModel Email Validation
如何使用 combine 验证合并这两个代码的视图模型中的电子邮件?
这是在我的 RegisterViewModel 里面
private var isEmailValidPublisher: ValidatePublisher {
$email
.removeDuplicates()
.map { [=10=].trimmingCharacters(in: .whitespacesAndNewlines).count >= 10}
.handleEvents(receiveOutput: { [weak self] in [=10=] ? (self?.emailMessage = "") : (self?.emailMessage = "Invalid email")})
.eraseToAnyPublisher()
}
我想在 isEmailValidPublisher 中添加此验证。
func isValidEmail() -> Bool {
let emailRegEx = "(?:[\p{L}0-9!#$%\&'*+/=?\^_`{|}~-]+(?:\.[\p{L}0-9!#$%\&'*+/=?\^_`{|}" + "~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\" + "x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[\p{L}0-9](?:[a-" + "z0-9-]*[\p{L}0-9])?\.)+[\p{L}0-9](?:[\p{L}0-9-]*[\p{L}0-9])?|\[(?:(?:25[0-5" + "]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + "9][0-9]?|[\p{L}0-9-]*[\p{L}0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21" + "-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"
let emailValidation = NSPredicate(format:"SELF MATCHES[c] %@", emailRegEx)
return emailValidation.evaluate(with: self)
}
我如何将它们混合在 isEmailValidPublisher 中,以便我可以在我的注册视图中使用该信息,如下所示
Image(systemName: "envelope")
.foregroundColor(registerVM.emailMessage != "" ? .red: .blue)
假设您有一个像这样的简单视图:
struct ContentView: View {
@StateObject var controller = Controller()
var body: some View {
VStack {
TextField("email", text: $controller.email)
.foregroundColor(controller.inputValid ? .primary : .red)
controller.validationMessage.map { message in
Text(message)
.foregroundColor(.red)
}
}
}
}
并且您想在 ObservableObject 中包含逻辑:
class Controller: ObservableObject {
@Published var email = ""
@Published private(set) var validationMessage: String?
var inputValid: Bool {
validationMessage == nil
}
init() {
// you subscribe to any changes to the email field input
$email
// you ignore the first empty value that it gets initialised with
.dropFirst()
// you give the user a bit of time to finish typing
.debounce(for: 0.6, scheduler: RunLoop.main)
// you get rid of duplicated inputs as they do not change anything in terms of validation
.removeDuplicates()
// you validate the input string and in case of problems publish an error message
.map { input in
guard !input.isEmpty else {
return "Email cannot be left empty"
}
guard input.isValidEmail() else {
return "Email is not valid"
}
// in case the input is valid the error message is nil
return nil
}
// you publish the error message for the view to react to
.assign(to: &$validationMessage)
}
}
如何使用 combine 验证合并这两个代码的视图模型中的电子邮件?
这是在我的 RegisterViewModel 里面
private var isEmailValidPublisher: ValidatePublisher {
$email
.removeDuplicates()
.map { [=10=].trimmingCharacters(in: .whitespacesAndNewlines).count >= 10}
.handleEvents(receiveOutput: { [weak self] in [=10=] ? (self?.emailMessage = "") : (self?.emailMessage = "Invalid email")})
.eraseToAnyPublisher()
}
我想在 isEmailValidPublisher 中添加此验证。
func isValidEmail() -> Bool {
let emailRegEx = "(?:[\p{L}0-9!#$%\&'*+/=?\^_`{|}~-]+(?:\.[\p{L}0-9!#$%\&'*+/=?\^_`{|}" + "~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\" + "x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[\p{L}0-9](?:[a-" + "z0-9-]*[\p{L}0-9])?\.)+[\p{L}0-9](?:[\p{L}0-9-]*[\p{L}0-9])?|\[(?:(?:25[0-5" + "]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-" + "9][0-9]?|[\p{L}0-9-]*[\p{L}0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21" + "-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"
let emailValidation = NSPredicate(format:"SELF MATCHES[c] %@", emailRegEx)
return emailValidation.evaluate(with: self)
}
我如何将它们混合在 isEmailValidPublisher 中,以便我可以在我的注册视图中使用该信息,如下所示
Image(systemName: "envelope")
.foregroundColor(registerVM.emailMessage != "" ? .red: .blue)
假设您有一个像这样的简单视图:
struct ContentView: View {
@StateObject var controller = Controller()
var body: some View {
VStack {
TextField("email", text: $controller.email)
.foregroundColor(controller.inputValid ? .primary : .red)
controller.validationMessage.map { message in
Text(message)
.foregroundColor(.red)
}
}
}
}
并且您想在 ObservableObject 中包含逻辑:
class Controller: ObservableObject {
@Published var email = ""
@Published private(set) var validationMessage: String?
var inputValid: Bool {
validationMessage == nil
}
init() {
// you subscribe to any changes to the email field input
$email
// you ignore the first empty value that it gets initialised with
.dropFirst()
// you give the user a bit of time to finish typing
.debounce(for: 0.6, scheduler: RunLoop.main)
// you get rid of duplicated inputs as they do not change anything in terms of validation
.removeDuplicates()
// you validate the input string and in case of problems publish an error message
.map { input in
guard !input.isEmpty else {
return "Email cannot be left empty"
}
guard input.isValidEmail() else {
return "Email is not valid"
}
// in case the input is valid the error message is nil
return nil
}
// you publish the error message for the view to react to
.assign(to: &$validationMessage)
}
}