如何将ViewController中的输入验证函数迁移至MVP架构?
基于MVP架构拆分密码验证UI逻辑的实现方案
核心思路
把原ViewController里的验证逻辑和UI更新触发逻辑剥离到Presenter层,让ViewController只负责接收用户输入、响应Presenter的指令更新UI,贴合MVP架构中「View只管展示、Presenter处理业务逻辑」的分工原则。
具体实现步骤
1. 定义View协议(MVP中View的抽象约定)
先定义一个协议,明确View需要实现的UI更新方法,让ViewController遵守该协议:
protocol PasswordValidationView: AnyObject { /// 更新长度验证标记的显示状态 func updateLengthCheckmark(hidden: Bool) /// 更新大写字母验证标记的显示状态 func updateUppercaseCheckmark(hidden: Bool) /// 更新数字验证标记的显示状态 func updateNumberCheckmark(hidden: Bool) /// 更新特殊字符验证标记的显示状态 func updateSymbolCheckmark(hidden: Bool) /// 更新重置按钮的显示状态 func updateResetButton(hidden: Bool) }
2. 创建Presenter类(封装业务逻辑)
Presenter持有View的弱引用,把原ViewController里的验证逻辑迁移过来,计算完状态后通过协议通知View更新UI:
class PasswordValidationPresenter { weak var view: PasswordValidationView? func validatePassword(_ text: String?) { guard let password = text else { // 空输入时隐藏所有验证标记和按钮 view?.updateLengthCheckmark(hidden: true) view?.updateUppercaseCheckmark(hidden: true) view?.updateNumberCheckmark(hidden: true) view?.updateSymbolCheckmark(hidden: true) view?.updateResetButton(hidden: true) return } let hasMinimumLength = TextValidationHelper.validateHasMinimumLength(password: password) let hasCapitalLetter = TextValidationHelper.validateHasCapitalLetter(password: password) let hasNumber = TextValidationHelper.validateHasNumber(password: password) let hasSpecialCharacter = TextValidationHelper.validateHasSpecialCharacter(password: password) // 通知View更新各个UI组件状态 view?.updateLengthCheckmark(hidden: !hasMinimumLength) view?.updateUppercaseCheckmark(hidden: !hasCapitalLetter) view?.updateNumberCheckmark(hidden: !hasNumber) view?.updateSymbolCheckmark(hidden: !hasSpecialCharacter) let allConditionsMet = hasMinimumLength && hasCapitalLetter && hasNumber && hasSpecialCharacter view?.updateResetButton(hidden: !allConditionsMet) } }
3. 修改ViewController(作为MVP的View层)
ViewController实现PasswordValidationView协议,初始化Presenter并绑定关联,把原IBAction的逻辑简化为传递输入给Presenter:
class YourViewController: UIViewController, PasswordValidationView { // 原有的UI组件声明 @IBOutlet weak var passLengthCheckmarkImageView: UIImageView! @IBOutlet weak var passHasUppercaseCheckmarkImageView: UIImageView! @IBOutlet weak var passHasNumberCheckmarkImageView: UIImageView! @IBOutlet weak var passHasSymbolCheckmarkImageView: UIImageView! @IBOutlet weak var resetButton: UIButton! // 初始化Presenter let validationPresenter = PasswordValidationPresenter() override func viewDidLoad() { super.viewDidLoad() // 绑定Presenter与View的关联 validationPresenter.view = self } // 原输入响应方法,现在仅负责传递输入内容给Presenter @IBAction func onEmailValueChanged(_ sender: UITextField) { validationPresenter.validatePassword(sender.text) } // 实现PasswordValidationView协议的UI更新方法 func updateLengthCheckmark(hidden: Bool) { passLengthCheckmarkImageView.isHidden = hidden } func updateUppercaseCheckmark(hidden: Bool) { passHasUppercaseCheckmarkImageView.isHidden = hidden } func updateNumberCheckmark(hidden: Bool) { passHasNumberCheckmarkImageView.isHidden = hidden } func updateSymbolCheckmark(hidden: Bool) { passHasSymbolCheckmarkImageView.isHidden = hidden } func updateResetButton(hidden: Bool) { resetButton.isHidden = hidden } }
是否需要更多代码?
你当前提供的代码已经足够完成MVP架构的拆分。如果TextValidationHelper有特殊依赖、或者ViewController还有其他关联业务逻辑(比如密码提交、额外错误提示),补充相关代码可以让方案更贴合你的实际场景,但现有信息已经能给出完整的核心拆分方案。
内容的提问来源于stack exchange,提问作者fabiobh
相关产品推荐
相关产品推荐

