Я долго искал решение этой проблемы и пока не нашел его.
Я разрабатываю приложение iOS с основными данными. Я создал два контекста управляемых объектов (MOC), которые указывают на один и тот же координатор постоянного хранилища. Один MOC (называемый self.moc) инициируется с параллелизмом основной очереди, тогда как другой mov (называемый self.bmoc) инициируется с параллелизмом частной очереди. Я убедился, что self.moc работает только в основном потоке, а self.bmoc работает только в пределах своего блока performBlock
или performBlockAndWait
.
Однако я столкнулся с этой странной ситуацией, когда мое приложение зависает на строке [self.bmoc save:nil]
. Поскольку действие сохранения выполняется в блоке performBlock
, я не вижу причин, по которым оно может зайти в тупик. Поскольку он зависает на этой строке, я не могу получить сообщение об ошибке, даже если использую [self.bmoc save:&error]
, а не nil
.
Ниже приведен код, который воспроизведет проблему. Хотя у меня есть много функций, похожих на приведенную ниже, только эта создает проблему. Я не могу понять причину проблемы, и любое понимание очень ценится. Благодарю вас!
-(void)createEmptyUserData {
[self.bmoc performBlock:^{
User* user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:self.bmoc];
/* sets user object */
[self.bmoc save:nil];
}];
}
Примечание. Этот фрагмент кода выполняется в основном потоке.
[self.bmoc save:nil];
вызываетcontextDidChange:
после завершения процесса сохранения. В моемcontextDidChange:
у меня было[self.moc performBlockAndWait^{ //mergeContext }]
. Как я уже упоминал в комментарии под своим вопросом, мой основной поток продолжается и заканчивается на[self.bmoc performBlockAndWait^{}]
. Проблема должна стать ясной: обе очереди ждут завершения друг друга, что приводит к взаимоблокировке. Мое решение состоит в том, чтобы изменитьperformBlockAndWait
вcontextDidChange:
наlock
иunlock
. 15.07.2012[self.moc performBlock^{ /* whatever */ }]
вызывает взаимоблокировку, я полагаю, что должен использовать явную блокировку. 16.07.2012[moc save:]
, я выбираюperformBlockAndWait:
, а неperformBlock
. Причина этого, например, в том, что после того, как мойself.bmoc
сохранил полученные данные из Интернета, мойself.moc
должен немедленно получить доступ к данным и обновить пользовательский интерфейс. 17.07.2012