UITableView "cellForRowAt: indexPath" Иногда вызывается "init?(Кодер aDecoder: NSCoder)" на базовом атрибуте данных

У меня есть основной объект данных 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
    }

}

Я отображаю age экземпляра Person в пределах UITableViewCell, Этот экземпляр (person) имеет возрастное значение 10,0, т.е. person.age.value = 10.0так, что когда масштаб изменяется программно, сказать scale = 2.0 через UIStepper, UITableViewCell дисплеи 20.0 (т.е. scale * value).

Тем не менее, я считаю, что если я увеличу UIStepper достаточно раз в конце концов инициализация Age класс для Person называется во время tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell метод, который возвращает экземпляр Person в данный момент IndexPath, Это, очевидно, вызывает init?(coder aDecoder: NSCoder) метод в пределах Age вызываемый класс, который сбрасывает значение scale собственность на 1.

Почему это происходит, пожалуйста, и есть ли способ исправить это вообще? Я в идеале хочу значение scale свойство всегда оставаться тем, что установлено на UIStepper,

Спасибо за любую помощь в этом вопросе.

РЕДАКТИРОВАТЬ

Данный person загар indexPath получается следующим образом:

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

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

1 ответ

Решение

Ваш 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)
Другие вопросы по тегам