Основные данные - Отменить изменения
Надеюсь, кто-то может объяснить, что происходит.
Если я получаю объект из модели Core Data, измените свойство, которое не сохраняется или даже определено в модели! а затем уничтожить и снова получить объект, значение по-прежнему установлено ранее.
Почему это?
Promotion *promotion = [Promotion promotionWithId:[NSNumber numberWithInt:1512] inManagedObjectContext:context];
[promotion setQuantity:[NSNumber numberWithInt:2]];
NSLog(@"%d", [promotion.quantity intValue]);
promotion = nil;
promotion = [Promotion promotionWithId:[NSNumber numberWithInt:1512] inManagedObjectContext:context];
NSLog(@"%d", [promotion.quantity intValue]);
promotion = nil;
Выход:
2
2
Для информационных целей:
+(Promotion *)promotionWithId:(NSNumber *)promotionId inManagedObjectContext:(NSManagedObjectContext *) context {
NSFetchRequest *fetchReq = [[NSFetchRequest alloc]init];
[fetchReq setEntity:[NSEntityDescription entityForName:@"Promotion" inManagedObjectContext:context]];
NSPredicate *query = [NSPredicate predicateWithFormat:@"promotionId=%d", [promotionId intValue]];
[fetchReq setPredicate:query];
NSMutableArray *resultArray = [[NSMutableArray alloc]initWithArray:[context executeFetchRequest:fetchReq error:nil]];
if([resultArray count] > 0) {
return [resultArray objectAtIndex:0];
}
return nil;
}
Ответы
Ответ 1
Имейте в виду, что изменения, которые вы делаете для всех управляемых объектов, сохраняются в контексте объекта управляемого объекта Coredata, пока вы не сохраните их (то есть сохраните контекст).
Итак, в вашем случае вы вносите изменения в управляемый объект, устанавливая его ссылку на ноль, но не перезагружая контекст.
Это означает, что ваше изменение все еще действует, и в следующий раз, когда вы получите тот же объект, он будет применен.
Чтобы полностью избавиться от него, вам понадобится reset контекст с помощью:
[context reset];
Из документации метода NSManagedObjectContext reset:
Все объекты, управляемые получателем, "забыты". Если вы используете это метод, вы должны убедиться, что вы также отбрасываете ссылки на любые управляемые объекты, извлеченные с помощью приемника, поскольку они будут недействительными после этого.
Ответ 2
Основные данные кэшируют объекты, а кеш может содержать ивары, которые не определены.
Попробуйте [context refreshObject:promotion mergeChanges:NO]
, затем оператор журнала.
Ответ 3
У вас есть несколько ошибок в коде, и я попытался объяснить, что происходит в списке рассылки RestKit. Позвольте мне просто вставить ответ здесь (с несколькими исправлениями, чтобы сделать текст более понятным).
Естественно, что контекст управляемого объекта даже не знает свойства, которое не определено в модели, и не является постоянным хранилищем объектов. Следовательно, должно быть что-то еще.
Посмотрите на свой код. Вы ударили в promotion = nil;
- который не освобождает объект. В этой части кода у вас нет утечки, но объект не будет выпущен на этом этапе. Этот объект хранится в resultArray.
Итак, когда объект освобождается? Он будет выпущен вместе с resultArray
. Вы не освобождаете resultArray
, который вы выделили в +promotionWithId:inManagedObjectContext:
. Вы не освобождаете его вообще. Также, кажется, нет причин для преобразования массива результатов в изменчивый массив в первую очередь.
Два варианта решения:
NSArray *resultArray = [context executeFetchRequest:fetchReq error:nil];
или
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithArray:[context executeFetchRequest:fetchReq error:nil]];
[resultArray autorelease];
Это и автореализованные объекты. Если вы пройдете маршрут автореферата, объект будет освобожден, как только будет удален или выпущен ближайший пул авторесурсов. Вы можете добавить свой пул авторезистов, обернув код в: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
а также [релиз пула];
Без этого ближайший пул авторесурсов, вероятно, находится в главном цикле Cocoa. Таким образом, resultArray
(и, следовательно, ваш результирующий объект) будет выпущен в главном цикле Cocoa.
Вы можете освободить resultArray
непосредственно внутри +promotionWithId:inManagedObjectContext:
, но не перед сохранением и автореализацией [resultArray objectAtIndex:0];
Итак, что должно произойти, когда вы отпускаете объект? Он должен, мы надеемся, быть удаленным из контекста управляемого объекта, и любая извлеченная копия должна быть ошибкой (поскольку оригинальная версия должна быть или должна исчезнуть). Честно говоря, я поражен тем, что в первую очередь возвращается одна и та же копия объекта (и спасибо за задание этого вопроса), но это логично, так как Core Data - это просто диспетчер графа объектов, который, как правило, поставляется с высокопроизводительный уровень сохранения.
Вы также можете вручную превратить объект в неисправность:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFaultingUniquing.html
Надеюсь, это поможет!