从 UITableViewCell 保存到 UserDefaults 导致崩溃 Swift 4.2

Saving to UserDefaults from UITableViewCell causes crash Swift 4.2

一个 UISwitch 被放置在一个 UITableViewCell 中,当开关被切换时想要将开关的状态保存到 UserDefaults。

class SettingsTableViewCell: UITableViewCell {
   @objc fileprivate func switchToggled(_ cellSwitch: UISwitch) {
        if let option = self.option {
            switch option.tag {
            case 1:
                let state = cellSwitch.isOn
                SettingsValues.standard.setState(state)
            default:
                print(">>> Settings Cell >> Tag for option does not exist")
            }
        }
    }
 }

在 viewDidLoad 上它工作正常并保存到 UserDefaults,但是当您将单元格滚动到屏幕外时,它就会出队。当您向后滚动并翻转开关时,它会导致崩溃:

EXC_BAD_ACCESS(code=1, address=0x20)

SettingsValues是自定义单例,函数保存到UserDefaults。我尝试通过协议将保存从 UITableViewCell 移出到 ViewController,但在保存到 UserDefaults 时仍然会导致崩溃。

我觉得这与 TableViewCell 的出队性质有关,但我不明白发生了什么,因此不确定如何解决这个问题。

编辑: 单例

final class SettingsValues: NSObject {
   static let standard = SettingsValues()

   private override init() { super.init() }

   @objc dynamic var state: Bool = UserDefaults.standard.bool(forKey: kEnableState) {
       didSet {
           saveSettingsState()
       }
   }

   private func saveSettingsState() {
        UserDefaults.standard.set(state, forKey: kEnableState)
   }

   func setState(_ bool: Bool) {
        self.state = bool
   }
}

崩溃在线UserDefaults.standard.set(state, forKey: kEnableState)。 我在该行设置了一个断点,当我按 step over 时,EXC_BAD_ACCESS 发生

我发现了这个错误。这是因为观察者。 tableView 中还有另一个单元格,其中有一个状态观察器。我没有在 deinit 上删除观察者,因此每次单元格出队和重新绘制时都会添加观察者的多个实例。

给大家上一课,看看你的观察者为同一个参考对象创建了多少次。我不会一直在 deinit 上删除,有时 deinit 永远不会被调用。示例:tabbarcontroller 上的 viewcontroller。 更安全的做法是观察创建实例的数量。在这种情况下,我应该删除 deinit

上的观察者

感谢所有发表评论并帮助解决问题的人