2012-05-04 2 views
8

При использовании NSPrivateQueueConcurrencyType и NSMainQueueConcurrencyType типов для NSManagedObjectContext, это безопасно сделать вложенные performBlock вызовы на том же контексте?Уплотненный performBlock: на NSManagedObjectContext

[backgroundContext performBlock:^{ 
    NSFetchRequest *myRequest = ...; 
    __block NSArray *result= nil; 
    [backgroundContext performBlockAndWait:^{ 
     results = [backgroundContext executeFetchRequest:myRequest error:NULL]; 
    }]; 
}]; 

Это может показаться глупым, но у меня есть существующий кодовый с большим количеством методов хелперов, которые инкапсулировать executeFetchRequest вызов. Я не хочу делать предположения о том, что вызывающий абонент уже использовал executeBlock или нет. Например:

-(void)updateObjects:(BOOL)synchronous 
{ 
    if (YES == synchronous) 
     [self fetchHelper]; 
    else 
    { 
     [backgroundContext performBlock:^{ 
      [self fetchHelper]; 
     }]; 
    } 
} 

-(NSArray*)fetchHelper 
{ 
    [self.backgroundContext performBlockAndWait:^{ 
     //Fetch the objects... 
     [self.backgroundContext executeFetchRequest: (...)]; 
    }]; 
} 

Я попробовал это, и это работает. Но я научился (трудный путь) быть очень осторожным с Core Data и многопоточными.

ответ

8

Да, performBlockAndWait является реентерабельным. Непосредственно из примечания к выпуску Apple, ...

Основные данные формализует модель параллелизма для NSManagedObjectContext класса с новыми возможностями. Когда вы создаете контекст , вы можете указать шаблон параллелизма для использования с ним: ограничение по контенту, частная диспетчерская очередь или основная отправка очередь. Параметр NSConfinementConcurrencyType обеспечивает тот же самый поведение , который присутствовал в версиях iOS до 5.0 и является значением по умолчанию. При отправке сообщений в контекст, созданный с помощью ассоциации очереди, вы должны использовать метод performBlock: или executeBlockAndWait: , если ваш код еще не выполняется в этой очереди (для основного типа очереди ) или в пределах области выполнения. .. invocation (для типа частной очереди). В пределах блоков, переданных этим методам , вы можете свободно использовать методы NSManagedObjectContext. Метод выполнения executeBlockAndWait: поддерживает повторное использование API. Метод executeBlock: включает в себя пул автоопределений и после завершения процесса обрабатывает метод обработки processPendingChanges.

+0

Как насчет выполнения блокировки, это тоже реенрант? – malhal

+0

Это не так, это рассматривается в сеансе. Ваши запросы будут стоять в очереди, если вы вызоверуете executeBlock, так как это асинхронно. –

+0

только для того, чтобы быть понятным, что делает OP во втором бите кода, нормально делать ?, но это может вызвать проблемы, если оба метода имеют «performBlock»? это правильный способ взглянуть на это? – hokkuk