UITableView "cellForRowAt: indexPath" 偶尔调用 "init?(coder aDecoder: NSCoder)" 核心数据属性
UITableView "cellForRowAt: indexPath" Occasionally Calling "init?(coder aDecoder: NSCoder)" on Core Data Attribute
我有一个核心数据实体 Person
,其可转换属性 age
类型为 Age
。
final class Person: NSManagedObject {
@NSManaged public fileprivate(set) var age: Age
}
Age
采用NSCoding
协议,有两个变量value
和scale
,但只保存了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
}
}
我在 UITableViewCell
中显示 Person
实例的 age
。此实例 (person
) 的年龄值为 10.0,即 person.age.value = 10.0
,因此当通过 UIStepper
以编程方式将比例更改为 scale = 2.0
时,UITableViewCell
显示 20.0
(即 scale * value
)。
但是,我发现如果我将 UIStepper
增加足够的次数,最终 Age
class 的初始化Person
在 tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
方法期间被调用,returns 在给定的 IndexPath
处 Person
的一个实例。这显然会导致调用 Age
class 中的 init?(coder aDecoder: NSCoder)
方法,从而将 scale
属性 的值重置为 1。
为什么会发生这种情况,有没有办法解决这个问题? 我理想情况下希望 scale
属性 的值是始终保持在 UIStepper
.
上的设置
感谢您对此事的任何帮助。
编辑
在 indexPath
处给定的 person
通过以下方式获得:
private var people: [Person] {
return Array(database.people).sortedArray(using: Person.defaultSortDescriptors)
}
private func person(at indexPath: IndexPath) -> Person {
return people[indexPath.item]
}
你的 people
属性 是一个 computed property,这意味着你每次通过 people[indexPath.item]
访问它时都会得到一个新的 people 数组。所以你每次调用 func person(at:)
时都会初始化一个新的 Person 实例,我猜这在 tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
.
通过更改步进值进行测试,然后使单元格从屏幕上消失并返回到同一单元格。那么年龄就已经重置了。
只需像这样将您的人员数组存储 属性。
private var people: [Person] = Array(database.people).sortedArray(using: Person.defaultSortDescriptors)
我有一个核心数据实体 Person
,其可转换属性 age
类型为 Age
。
final class Person: NSManagedObject {
@NSManaged public fileprivate(set) var age: Age
}
Age
采用NSCoding
协议,有两个变量value
和scale
,但只保存了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
}
}
我在 UITableViewCell
中显示 Person
实例的 age
。此实例 (person
) 的年龄值为 10.0,即 person.age.value = 10.0
,因此当通过 UIStepper
以编程方式将比例更改为 scale = 2.0
时,UITableViewCell
显示 20.0
(即 scale * value
)。
但是,我发现如果我将 UIStepper
增加足够的次数,最终 Age
class 的初始化Person
在 tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
方法期间被调用,returns 在给定的 IndexPath
处 Person
的一个实例。这显然会导致调用 Age
class 中的 init?(coder aDecoder: NSCoder)
方法,从而将 scale
属性 的值重置为 1。
为什么会发生这种情况,有没有办法解决这个问题? 我理想情况下希望 scale
属性 的值是始终保持在 UIStepper
.
感谢您对此事的任何帮助。
编辑
在 indexPath
处给定的 person
通过以下方式获得:
private var people: [Person] {
return Array(database.people).sortedArray(using: Person.defaultSortDescriptors)
}
private func person(at indexPath: IndexPath) -> Person {
return people[indexPath.item]
}
你的 people
属性 是一个 computed property,这意味着你每次通过 people[indexPath.item]
访问它时都会得到一个新的 people 数组。所以你每次调用 func person(at:)
时都会初始化一个新的 Person 实例,我猜这在 tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
.
通过更改步进值进行测试,然后使单元格从屏幕上消失并返回到同一单元格。那么年龄就已经重置了。
只需像这样将您的人员数组存储 属性。
private var people: [Person] = Array(database.people).sortedArray(using: Person.defaultSortDescriptors)