РАЗРАБОТКА IPHONE/IPOD TOUCH ПРИЛОЖЕНИЙ: ОБРАТНЫЕ СВЯЗИ В МОДЕЛИ ДАННЫХ COREDATA
Когда возникает необходимость создать в модели отношение «один ко многим» (такое, как показано на рисунке),

то может показаться, что обратные отношения ставить незачем, как и при отношениях «один к одному» . И действительно, ваше приложение запустится и не будет падать из-за этого, хотя компилятор и выдаст вам Warning’и. Но не все так просто…
Рассмотрим этот случай на примере магазина, в котором содержатся товары. Для этого нам потребуется две сущности: Store и Item. Store содержит отношение items к сущности Item как один ко многим.
Множественное отношение items представляется в классе Store - наследнике класса NSManagedObject как property типа NSSet. Так же для того, чтобы добавлять товары в магазин и удалять их оттуда, нам потребуется объявить accessor-методы, которые можно сгенерировать из модели (находим в модели сущность Store -> правый клик на отношении items -> “Copy Obj-C 2.0 Method Declarations to Clipboard”) . Теперь, когда модель готова, импортировав хэдер класса Store, мы можем использовать эти accessor – методы. Ниже приведен пример хэдера класса Store:

@class Item;
@interface Store : NSManagedObject {
}
@property (nonatomic, retain) NSSet* items;
@end
@interface Store (CoreDataGeneratedAccessors)
- (void)addItemsObject:(Item *)value;
- (void)removeItemsObject:(Item *)value;
- (void)addItems:(NSSet *)value;
- (void)removeItems:(NSSet *)value;
@end
После добавления новых товаров при помощи метода addItemsObject: и сохранения контекста все впорядке – после рестарта приложения добавленные объекты присутствуют в хранилище. Но вот если удалить какой-нибудь товар методом removeItemsObject: и сохранить контекст, то после рестарта, а может и раньше, можно будет заметить, что этот товар снова появится в наборе items в контексте, хотя ошибку сохранения нам не вернут. Т.е. реально в базе связь не удалилась.
Чтобы этого не происходило, следует в модели создать обратное отношение (Inverse relationship) «один к одному» (как в данном случае) либо «один ко многим» у сущности Item к сущности Store (назовем его store), и модифицировать класс Item соответствующим образом.

Теперь удаление товаров будет происходить корректно.
Почему так получилось? Вероятно, при сохранении в хранилище после удаления эти обратные отношения используются на уровне sql-запросов.
P. S. В статье рассматривается случай, когда используется SQLite-хранилище CoreData.














Alex§
в 11:35, 05.08.2009Интересное наблюдение. В какой программке составлялись диаграммы, если не секрет?
Павел Тайкало
в 13:45, 05.08.2009И совсем не секрет
Xcode 3.1.2
Илья Кулаков
в 12:28, 11.08.2009Вообще в своем гайде Apple не рекомендует использовать односторонние relationship. Там же приводят несколько возможных путей решения задачи.
А вы пробовали смотреть deletedObjects у контекста? Присутствует ли там удаленные объект?
Евгений Дудник
в 12:46, 11.08.2009Вы спрашиваете об удалении объекта store и каскадном удалении item или только объекта item (если использовать пример в статье)?
Илья Кулаков
в 20:35, 11.08.2009Мда, глупость какую-то сморозил. Почудилось будто вы Item удаляете из контекста а не из Store.
Вообще вот вырезка из Core Data Programmin Guide:
If you create a model with unidirectional relationships (relationships where you have specified no inverse), your object graph may end up in an inconsistent state.
Евгений Дудник
в 21:32, 11.08.2009Apple, конечно, упоминает вскользь о том что может быть если вы сделаете не так, как они рекомендуют. Но, на это нужно обращать внимание и не забывать об этом. Эта статья – описание ситуации с обратной стороны – когда вы столкнулись с таким багом и не можете быстро найти причину (сам вот потратил не мало времени на это, после чего и решил написать).