SwiftUI 结合 ViewModel 电子邮件验证
Posted
技术标签:
【中文标题】SwiftUI 结合 ViewModel 电子邮件验证【英文标题】:SwiftUI Combine ViewModel Email Validation 【发布时间】:2021-10-07 08:17:57 【问题描述】:如何使用 combine 验证结合这两个代码的视图模型中的电子邮件?
这是在我的 RegisterViewModel 中
private var isEmailValidPublisher: ValidatePublisher
$email
.removeDuplicates()
.map $0.trimmingCharacters(in: .whitespacesAndNewlines).count >= 10
.handleEvents(receiveOutput: [weak self] in $0 ? (self?.emailMessage = "") : (self?.emailMessage = "Invalid email"))
.eraseToAnyPublisher()
我想在 isEmailValidPublisher 中添加此验证。
func isValidEmail() -> Bool
let emailRegEx = "(?:[\\pL0-9!#$%\\&'*+/=?\\^_`|~-]+(?:\\.[\\pL0-9!#$%\\&'*+/=?\\^_`|" + "~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\" + "x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\pL0-9](?:[a-" + "z0-9-]*[\\pL0-9])?\\.)+[\\pL0-9](?:[\\pL0-9-]*[\\pL0-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]?|[\\pL0-9-]*[\\pL0-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)
【问题讨论】:
我假设isValidEmail()
是String 类的扩展?
确实如此。 @丹尼尔T。有什么改变吗?
【参考方案1】:
假设你有一个像这样的简单视图:
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)
【讨论】:
以上是关于SwiftUI 结合 ViewModel 电子邮件验证的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:从 ViewModel 更改视图 @State 属性
如何在 SwiftUI 中通过 ViewModel 传播模型更改?