【问题标题】:Saving to UserDefaults from UITableViewCell causes crash Swift 4.2从 UITableViewCell 保存到 UserDefaults 导致崩溃 Swift 4.2
【发布时间】:2018-11-13 08:54:30
【问题描述】:

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 出现

【问题讨论】:

  • 设置一个异常断点来确定崩溃发生的确切位置。您的代码看起来无害。
  • 我怀疑这段代码会崩溃。设置异常断点以获取更多信息。基本上UserDefaults 不适合在表格视图中保存 UI 状态。向数据模型添加一个属性以保持状态。
  • 你在哪里设置 switchToggled 动作??发布完整的上下文
  • 我添加了单例。问题是当 viewController 加载并且您不滚动表格以使单元格消失时,您可以根据需要多次翻转开关。但是,当您向后滚动并翻转开关时,该单元格滚动到屏幕外的那一刻,它就会崩溃。但是保存仍然会发生,所以当您再次打开应用程序时,布尔值会被保存。我使用了自定义单例,因为我附加了一个观察者。
  • 我正在保存应用程序再次打开时的状态。

标签: swift uitableview nsuserdefaults swift4.2


【解决方案1】:

我发现了错误。这是因为观察者。 tableView 中的另一个牢房有一个国家观察员。我没有删除deinit上的观察者,因此每次单元格出列和重绘时都会添加多个观察者实例。

所有的课程都要注意观察者为同一个参考对象创建了多少次。我不会走得太远总是删除deinit,有时deinit 永远不会被调用。示例:tabbarcontroller 上的视图控制器。 更安全的选择是观察创建的实例的数量。在这种情况下,我应该删除deinit上的观察者

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 2016-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多