You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift iOS:选中BEMCheckBox时UserDefaults保存账号密码失效问题

问题排查与解决方案

看起来你的核心问题是复选框选中时的保存逻辑没有被正确触发,我帮你梳理几个关键问题和修复方案:

1. 未遵循BEMCheckBoxDelegate协议

你设置了box1.delegate = self,但你的ViewController没有明确遵循BEMCheckBoxDelegate协议,导致复选框点击时的代理方法didTap(_:)根本不会被调用。这是最关键的问题!

2. viewDidLoad方法的调用顺序错误

你在viewDidLoad里先调用了didTap(box1),然后才设置代理,最后调用checkSavedData()。这个顺序会导致:

  • 页面加载时就触发一次保存/删除操作,可能覆盖之前的正确数据
  • 代理设置晚于主动调用,逻辑混乱

3. 键名定义的小问题

keys结构体里的boxBool用了var,它作为固定的键名应该是常量,改成let更合理。

修正后的完整代码

import UIKit
import BEMCheckBox

class ViewController: UIViewController {
    let defaults = UserDefaults.standard
    @IBOutlet weak var box1: BEMCheckBox!
    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    
    struct Keys {
        static let emailKey = "emailTextField"
        static let passwordKey = "passwordTextField"
        static let boxBool = "boxBool" // 改为let常量,符合命名规范
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        box1.delegate = self // 先设置代理,确保点击事件能被监听
        checkSavedData() // 再恢复之前保存的数据
        // 移除主动调用didTap的代码,避免页面加载时误触发保存/删除逻辑
    }
    
    // 确保这个方法是BEMCheckBoxDelegate的代理方法
    func didTap(_ checkBox: BEMCheckBox) {
        if checkBox.on {
            rememberMyEmailandPassword()
        } else {
            defaults.removeObject(forKey: Keys.emailKey)
            defaults.removeObject(forKey: Keys.passwordKey)
            defaults.set(false, forKey: Keys.boxBool) // 直接设为false比移除键更稳妥
        }
    }
    
    func rememberMyEmailandPassword() {
        // 可选值绑定,避免保存空的邮箱或密码
        guard let email = emailTextField.text, !email.isEmpty,
              let password = passwordTextField.text, !password.isEmpty else {
            // 这里可以添加用户提示,比如"请输入完整的邮箱和密码"
            return
        }
        defaults.set(email, forKey: Keys.emailKey)
        defaults.set(password, forKey: Keys.passwordKey)
        defaults.set(box1.on, forKey: Keys.boxBool)
    }
    
    func checkSavedData() {
        // 用string(forKey:)代替value(forKey:),类型转换更安全直接
        let email = defaults.string(forKey: Keys.emailKey) ?? ""
        let password = defaults.string(forKey: Keys.passwordKey) ?? ""
        let boxBoolean = defaults.bool(forKey: Keys.boxBool)
        
        emailTextField.text = email
        passwordTextField.text = password
        box1.on = boxBoolean
    }
}

// 必须添加这个扩展,让ViewController遵循BEMCheckBoxDelegate协议,代理方法才能生效
extension ViewController: BEMCheckBoxDelegate {}

额外优化点说明

  • 调整了变量和结构体的命名,符合Swift的命名规范(小写开头的实例变量,大写开头的结构体)
  • 在保存逻辑里添加了空值判断,避免保存无效的空内容
  • 取消选中时直接设置复选框状态为false,而不是移除键,让读取逻辑更稳定
  • 用string(forKey:)替代value(forKey:),减少不必要的类型转换

你可以试试这个修正后的代码,应该就能正常保存和恢复用户的邮箱、密码以及复选框状态了。

内容的提问来源于stack exchange,提问作者Nawaf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:30:25