Вложенные контексты UIManagedDocument

Я читал документы Apple и все еще есть вопрос, на который я не могу найти ответ. У меня есть объект UIManagedDocument, который имеет два вложенных контекста: дочерний в основном потоке и родительский в частном потоке. И далее у меня есть серверная часть. Итак, когда данные поступают с сервера, я хочу вставить их в мой управляемый документ в фоновом потоке.

Является ли он потокобезопасным, чтобы создать асинхронную очередь, создать там NSManagedObjectContext и установить в качестве родительского дочернего контекста UIManagedDocument, который создается в основном потоке?

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
     //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe?

    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");


});
dispatch_release(fetchQ);

Другими словами, является ли потокобезопасным назначение контекста, созданного в родительском частном потоке, который был создан в основном потоке?


person Andrew    schedule 10.04.2012    source источник


Ответы (2)


Вы используете частный тип параллелизма. Это означает, что вы должны запускать код в собственной очереди (через PerformBlock). Итак, если вы хотите сделать это, вы должны сделать это так...

NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parentContext = self.eventDatabase.managedDocument;
backgroundContext.performBlock:^{
    //here goes some code for downloading data from the server
    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");

    // Calling save on the background context will push the changes up to the document.
    NSError *error = nil;
    [backgroundContext save:&error];

    // Now, the changes will have been pushed into the MOC of the document, but
    // the auto-save will not have fired.  You must make this call to tell the document
    // that it can save recent changes.
    [self.eventDatabase updateChangeCount:UIDocumentChangeDone];
});

Если вы хотите самостоятельно управлять очередью, вам, вероятно, следует использовать конфайнментный MOC, вы должны инициализировать его с помощью NSConfinementConcurrencyType или со стандартной инициализацией, потому что это значение по умолчанию. Тогда это будет выглядеть так...

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
    backgroundContext.parentContext = self.eventDatabase.managedDocument;

    //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init];

    // Everything else is as in the code above for the private MOC.
});
dispatch_release(fetchQ);
person Jody Hagins    schedule 10.04.2012
comment
Кстати, не забудьте вызвать [backgroundContext save:&error], иначе изменения не будут переданы в родительский контекст. - person Jody Hagins; 12.04.2012
comment
почему бы ему просто не использовать parentContex UIManagedDocument, этот контекст работает в фоновом режиме? - person João Nunes; 18.02.2013

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

NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[addingContext setParentContext:[self.fetchedResultsController managedObjectContext]];

[addingContext performBlock:^{
    // do your stuffs
    [addingContext save:&error];

    [parent performBlock:^{
        [parent save:&parentError];
    }];
}];
person Lin Xuan    schedule 19.02.2013