如何重构Swift中onEditingChanged代码以实现协议复用?
重构Swift邮箱验证逻辑实现复用
方案1:将验证逻辑封装到FormModel中
把onEditingChanged内的逻辑提取为FormModel的方法,让所有需要邮箱验证的TextField都能直接调用。
修改FormModel代码:
class FormModel: ObservableObject { @Published var textEmail = "" @Published var isEmailValid = true // 原有邮箱验证规则 func textFieldValidatorEmail(_ email: String) -> Bool { let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}" let emailPred = NSPredicate(format:"SELF MATCHES %@", emailRegEx) return emailPred.evaluate(with: email) } // 封装编辑结束后的验证逻辑 func handleEmailEditingEnded() { if textFieldValidatorEmail(textEmail) { isEmailValid = true } else { isEmailValid = false textEmail = "" } } }
View中调用简化为:
TextField("Email address", text: $formModel.textEmail, onEditingChanged: { isChanged in if !isChanged { formModel.handleEmailEditingEnded() } }) if !formModel.isEmailValid { InvalidEmailView() }
方案2:用ViewModifier实现通用验证逻辑
如果需要脱离FormModel、适配更多输入验证场景,推荐用SwiftUI的ViewModifier封装:
struct EmailValidationModifier: ViewModifier { @Binding var text: String @Binding var isValid: Bool let validator: (String) -> Bool func body(content: Content) -> some View { content .onEditingChanged { isChanged in if !isChanged { isValid = validator(text) if !isValid { text = "" } } } } } // 扩展View,简化调用 extension View { func emailValidation(text: Binding<String>, isValid: Binding<Bool>, validator: @escaping (String) -> Bool) -> some View { self.modifier(EmailValidationModifier(text: text, isValid: isValid, validator: validator)) } }
使用方式:
TextField("Email address", text: $formModel.textEmail) .emailValidation(text: $formModel.textEmail, isValid: $formModel.isEmailValid) { email in formModel.textFieldValidatorEmail(email) } if !formModel.isEmailValid { InvalidEmailView() }
方案3:提取为可复用闭包(快速复用场景)
如果只是临时复用同一段逻辑,可以直接把闭包定义为变量:
// 在View内定义复用闭包 let emailEditingHandler: (Bool, FormModel) -> Void = { isChanged, model in if !isChanged { model.isEmailValid = model.textFieldValidatorEmail(model.textEmail) if !model.isEmailValid { model.textEmail = "" } } } // 调用时直接传入 TextField("Email address", text: $formModel.textEmail, onEditingChanged: { isChanged in emailEditingHandler(isChanged, formModel) })
三种方案适用场景:
- 方案1:适合业务逻辑与模型绑定紧密的场景,逻辑内聚性强
- 方案2:SwiftUI生态下的通用写法,支持灵活替换验证规则
- 方案3:快速实现复用的轻量化方案,适合小范围临时复用
内容的提问来源于stack exchange,提问作者Ashutosh Mukherjee
相关产品推荐
相关产品推荐

