Базовые данные - объект обновления в фоновом потоке автоматически меняет NSManagedObject в основном потоке без слияния - почему? - PullRequest
3 голосов
/ 18 декабря 2011

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

У меня есть объект с именем TestEntity с 2 атрибутами (testId и testDescription) В основном потоке я выбираю объектс testId = 1 и сохраните этот управляемый объект в переменной экземпляра.

    NSEntityDescription *entityDescription = [NSEntityDescription
                                          entityForName:@"TestEntity" inManagedObjectContext:self.managedObjectContext];

NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];

NSNumber *testId = [NSNumber numberWithInt:1];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"testId == %@", testId];
[request setPredicate:predicate];

NSError *error = nil;
NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error];

t1 = [[array objectAtIndex:0] retain];

TestThread *tt = [TestThread new];

NSOperationQueue *queue = [NSOperationQueue new];
[queue addOperation:tt];

[queue waitUntilAllOperationsAreFinished];
NSLog(@"%@", [t1 valueForKey:@"testDescription"]);

Затем запустите NSOperation с NSOperationQueue с именем TestThread.В основном методе этого TestThread я создаю второй контекст управляемого объекта, извлекаю ту же сущность (testId = 1), что и основной поток, изменяем свойство testDescription и сохраняем новый контекст без ошибок.

    tgAppDelegate *delegate = [[NSApplication sharedApplication] delegate];

self.context = [[[NSManagedObjectContext alloc] init] autorelease];
[context setPersistentStoreCoordinator:delegate.persistentStoreCoordinator];


NSEntityDescription *entityDescription = [NSEntityDescription
                                          entityForName:@"TestEntity" inManagedObjectContext:self.context];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];

// Set example predicate and sort orderings...
NSNumber *testId = [NSNumber numberWithInt:1];
NSPredicate *predicate = [NSPredicate predicateWithFormat:
                          @"testId == %@", testId];
[request setPredicate:predicate];

NSError *error = nil;

NSArray *array = [context executeFetchRequest:request error:&error];
TestEntity *t1 = [array objectAtIndex:0];

t1.testDescription = @"abc";
[context save:&error];
if (error) {
    // do something
}

Поведение, которое я не могу объяснить, заключается в том, что вывод NSLog после

[queue waitUntilAllOperationsAreFinished];

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

Может кто-нибудь объяснить, почему это происходит?

1 Ответ

1 голос
/ 21 декабря 2011

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

Чтобы увидеть ожидаемое поведение, попробуйте зарегистрировать исходное значение t1.testDescription перед запуском второго потока.

Вы также можете установить

self.context.returnObjectsAsFaults = NO;

но это может оказать негативное влияние на объем памяти вашего приложения.

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