Реализация переходных свойств

Я добавляю переходное свойство в свое приложение на основе Core Data и думаю, что что-то упускаю. В редакторе модели данных я добавил свойство optional, transient, BOOL с именем isUnderwater.

В заголовочный файл моей модели я добавил: @property (nonatomic) BOOL isUnderwater;, затем реализовал эти методы в файле реализации:

- (BOOL)isUnderwater {
    ... implementation ...
    return (ret);
}
- (void)setIsUnderwater:(BOOL)isUnderwater {}

Но когда я пытаюсь использовать isUnderwater в качестве условия в NSPredicate, я получаю эту ошибку: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath isUnderwater not found in entity <NSSQLEntity Wheel id=2>'.

Любые идеи?

Спасибо!


person Bill Smithed    schedule 24.08.2010    source источник
comment
В качестве альтернативы вы можете создать подходящий метод проверки NSManagedObject: stackoverflow.com/questions/1022284/   -  person PostCodeism    schedule 14.10.2010


Ответы (1)


Во-первых, вы не можете использовать временное свойство в NSFetchRequest, которое идет против хранилища SQLite. Когда вы используете SQLite, NSFetchRequest переводится в sql и запускается в базе данных задолго до того, как ваш переходный процесс будет затронут.

Кроме того, вам не следует реализовывать средства доступа, вместо этого вы должны использовать @synthesize.

Затем, если вы хотите установить переходное свойство, вы должны установить его в -awakeFromFetch и/или -awakeFromInsert вместо переопределения геттера.

Затем ваше свойство должно называться underwater, а определение @property должно быть:

@property (nonatomic, retain, getter=isUnderwater) NSNumber *underwater;

Примечание: несмотря на то, что вы объявляете его логическим в своей модели, в коде он по-прежнему является NSNumber.

Наконец, установка необязательного флага для переходного свойства не имеет значения, поскольку оно все равно будет отброшено.

Обновлять

Вы можете применять дополнительные фильтры (даже к временным свойствам), когда объекты находятся в памяти. Единственное ограничение заключается в том, что вы не можете использовать переходные свойства при переходе к файлу SQLite.

Например, вы можете выполнить NSFetchRequest, который загрузит все объекты. Затем вы можете сразу же применить второй NSPredicate к возвращенному NSArray и дополнительно отфильтровать объекты.

person Marcus S. Zarra    schedule 24.08.2010
comment
Это имеет смысл. Но как заполнить UITableView основными объектами данных, которые отфильтрованы на основе пользовательской логики, а не сохраненных/непереходных атрибутов? Например, если бы я хотел иметь возможность переключаться между всеми объектами типа и теми, у которых свойство переходного процесса установлено определенным образом (т. е. пройти определенный логический тест)? Я бы подумал использовать блоки, но они также недоступны для хранилища SQLite... - person Bill Smithed; 24.08.2010
comment
Вполне допустимо переопределить геттер (тем более, что ни вы, ни я понятия не имеем, что он там делает). Также идеально подходит использование BOOL для переходного свойства, которое на самом деле является BOOL. Нет никаких причин упаковывать и распаковывать в NSNumber, тем более что он предоставляет свой собственный подкласс NSManagedObject. Я часто делаю это с управляемыми атрибутами, которые поддерживаются примитивом, чтобы упростить доступ. - person Jason Coco; 24.08.2010
comment
@Jason Джейсон, переопределять средства доступа с помощью пользовательской логики - плохой тон. Если вы работаете со свойством, метод доступа должен обращаться только к значению; не выполнять пользовательскую логику. Кроме того, если вы объявляете переходный процесс NSNumber как BOOL, вы напрашиваетесь на неприятности. Может работать сегодня, но я серьезно сомневаюсь, что это будет работать всегда. Я не буду рекомендовать это. - person Marcus S. Zarra; 24.08.2010
comment
you could perform a NSFetchRequest that loads in all of the entities. You could then immediately apply a second NSPredicate against the returned NSArray and further filter the objects down. Значит ли это, что NSFetchedResultsController исключен? - person Bill Smithed; 24.08.2010
comment
Нет, просто немного сложнее. Вы по-прежнему можете использовать его для обнаружения изменений в данных, но вам нужно будет обновлять свой вторичный массив всякий раз, когда происходят эти изменения. Лично я нашел бы способ вместо этого сделать это временное свойство хранимым свойством. Денормализация данных, как правило, решает множество подобных проблем. - person Marcus S. Zarra; 24.08.2010