Подтвердить что ты не робот

Основные данные - Отменить изменения

Надеюсь, кто-то может объяснить, что происходит.

Если я получаю объект из модели 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;
}
4b9b3361

Ответ 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

Надеюсь, это поможет!