Основные данные - отменить изменения - PullRequest
14 голосов
/ 19 октября 2011

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

Если я получу объект из своей модели базовых данных, измените свойство, которое не сохраняется или даже не определено в модели! а затем уничтожить и получить объект снова, значение остается прежним.

Почему это?

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 * * +1010

Для информационных целей:

+(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;
}

Ответы [ 3 ]

24 голосов
/ 19 октября 2011

Помните, что изменения, которые вы вносите во все управляемые объекты, сохраняются в контексте управляемого объекта Coredata до тех пор, пока вы не сохраните их (т.е. сохраните контекст).

Таким образом, в вашем случае вы вносите изменения вуправляемый объект, устанавливая его ссылку на ноль, но не сбрасывая контекст.

Это означает, что ваше изменение остается в силе, и в следующий раз, когда вы получите тот же объект, оно будет применено.

Чтобы полностью избавиться от него, вам потребуется сбросить контекст с помощью:

[context reset];

Из документации по методу сброса NSManagedObjectContext:

Все управляемые объекты получателя «забыты». Если вы используете этот метод, вы должны также отменить ссылки на любые управляемыеобъекты, выбранные с использованием получателя, поскольку впоследствии они будут недействительными.

6 голосов
/ 19 октября 2011

Базовые данные кэшируют объекты, и в кэше могут храниться ивары, которые не являются определенными свойствами.

Попробуйте [context refreshObject:promotion mergeChanges:NO], затем оператор log.

0 голосов
/ 20 октября 2011

У вас есть несколько ошибок в коде, и я попытался объяснить, что происходит в списке рассылки 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];и [пул релиз];

Без этого ближайший пул автоматического выпуска, вероятно, находится в главном цикле выполнения Какао.Таким образом, resultArray (и, следовательно, ваш результирующий объект) будет освобожден в главном цикле выполнения Cocoa.

Возможно, вы захотите выпустить resultArray непосредственно внутри +promotionWithId:inManagedObjectContext:, но не перед сохранением и автоматическим выпуском[resultArray objectAtIndex:0];

Итак, что должно произойти, когда вы отпустите объект?Надеемся, что он должен быть удален из контекста управляемого объекта, и любая извлеченная копия должна быть ошибкой (поскольку исходная копия исчезла или должна исчезнуть).Честно говоря, я поражен тем, что в первую очередь возвращается одна и та же копия объекта (и спасибо, что задали этот вопрос) - но это логично, поскольку Core Data - это просто диспетчер графов объектов, который, удобно, поставляется свысокопроизводительный персистентный слой.

Вы также можете вручную превратить объект в неисправность: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreData/Articles/cdFaultingUniquing.html

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...