UITableView"cellForRowAt:indexPath"偶尔在核心数据属性上调用"init?(coder aDecoder:NSCoder)"

ale*_*wis 4 core-data uitableview ios transformable swift

我有一个核心数据实体Person,具有age类型的可转换属性Age.

final class Person: NSManagedObject {
    @NSManaged public fileprivate(set) var age: Age
}
Run Code Online (Sandbox Code Playgroud)

Age采用了NSCoding协议,有两个变量valuescale,但只有value保存:

class Age: NSObject, NSCoding {

    @objc public var value: Double
    public var scale = 1.0

    override public var description: String {
        return "\(scale * value)"
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(value, forKey: #keyPath(value))
    }

    public convenience required init?(coder aDecoder: NSCoder) {
        self.init(value: aDecoder.decodeDouble(forKey: #keyPath(value)))
    }

    init(value: Double) {
        self.value = value
    }

}
Run Code Online (Sandbox Code Playgroud)

我显示age的一个实例的PersonUITableViewCell.该实例(person)具有10.0的年龄值,即person.age.value = 10.0,当以编程方式改变比例以scale = 2.0通过a UIStepper,UITableViewCell显示20.0(即scale * value)时.

但是,我发现如果我增加UIStepper足够的时间,最终会在方法期间调用Age类的初始化,PersontableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell方法返回Person给定的实例IndexPath.这显然会导致调用类中的init?(coder aDecoder: NSCoder)方法Age,从而将scale属性的值重置为1.

请问为什么会发生这种情况,是否有办法解决这个问题?理想情况下,我希望scale属性的值始终保持在其上的设置值UIStepper.

感谢您对此事的任何帮助.

编辑

给定personindexPath是以下列方式获得的:

private var people: [Person] {
    return Array(database.people).sortedArray(using: Person.defaultSortDescriptors)
}

private func person(at indexPath: IndexPath) -> Person {
    return people[indexPath.item]
}
Run Code Online (Sandbox Code Playgroud)

sj-*_*j-r 5

您的people属性是计算属性,这意味着每次访问时都会获得一个新的人员数组people[indexPath.item].因此,每次调用时都要初始化一个新的Person实例func person(at:),我想这就是tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell.

通过更改步进器值进行测试,然后使单元格从屏幕上消失并返回到同一单元格.然后年龄将被重置.

只需让你的人员数组成为这样的存储属性.

private var people: [Person] = Array(database.people).sortedArray(using: Person.defaultSortDescriptors)
Run Code Online (Sandbox Code Playgroud)