I have a core data entity Person
with a transformable attribute age
of type Age
.
final class Person: NSManagedObject {
@NSManaged public fileprivate(set) var age: Age
}
Age
adopts the NSCoding
protocol and has two variables value
and scale
, but only the value
is saved:
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
}
}
I display the age
of an instance of Person
within a UITableViewCell
. This instance (person
) has an age value of 10.0, i.e. person.age.value = 10.0
, such that when the scale is changed programatically to say scale = 2.0
via a UIStepper
, the UITableViewCell
displays 20.0
(i.e. scale * value
).
However, I'm finding that if I increment the UIStepper
enough times eventually the initialisation of the Age
class for the Person
is called during the tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
method, which returns an instance of Person
at a given IndexPath
. This obviously causes the init?(coder aDecoder: NSCoder)
method within the Age
class to be called, which resets the value of the scale
property to 1.
Why does this happen, please, and is there a way fixed this at all? I ideally want the value of the scale
property to always remain what it is set to on the UIStepper
.
Thanks for any help on this matter.
EDIT
A given person
at an indexPath
is obtained in the following way:
private var people: [Person] {
return Array(database.people).sortedArray(using: Person.defaultSortDescriptors)
}
private func person(at indexPath: IndexPath) -> Person {
return people[indexPath.item]
}
Your people
property is a computed property, which means you get a new people array every time you access it by people[indexPath.item]
. So you are initializing a new Person instance every time you call func person(at:)
, which I guess in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
.
Test this by changing the stepper value, and then make the cell disappear from the screen and come back to the same cell. Then the age will have been reset.
Just make your people array a stored property like this.
private var people: [Person] = Array(database.people).sortedArray(using: Person.defaultSortDescriptors)