Что могло привести к сбою обновлений пользовательского интерфейса через dispatch_async при вызове из блока фоновой очереди?

Может ли кто-нибудь увидеть причину, по которой этот код будет нормально работать для обновления пользовательского интерфейса:

__block NSDictionary *result = nil;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);

[[SomeService sharedInstance] doSomethingGreatWithReplyBlock:^(NSDictionary * response) {
    result = response;
    dispatch_semaphore_signal(sema);
}];

dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

dispatch_async(dispatch_get_main_queue(), ^{
    [self updateDisplay:result];
});

Но этого не будет?

__block NSDictionary *result = nil;
[[SomeService sharedInstance] doSomethingGreatWithReplyBlock:^(NSDictionary * response) {
    dispatch_async(dispatch_get_main_queue(), ^{
       [self updateDisplay:response];
    });
}];

Разве это не то же самое? В первом примере я жду завершения асинхронной операции с использованием семафора. Затем dispatch_async в основной очереди.

Во втором я вызываю dispatch_async (также в основной очереди) непосредственно из другого блока (который выполняется в некоторой фоновой очереди). Он по-прежнему вызывает метод updateDisplay нормально, но на самом деле он не обновляет пользовательский интерфейс. Кажется, что это проблема с обновлением основного потока, однако [NSThread isMainThread] по-прежнему возвращает true ...

Есть ли какая-то очевидная разница, которую мне здесь не хватает? Я здесь довольно потерян и был бы признателен за любое объяснение. Я никогда раньше не наблюдал такого странного поведения.

Я сомневаюсь, что проблема заключается в очередях (включите дезинфицирующее средство основного потока, чтобы убедиться). Я подозреваю, что либо (а) updateDisplay на самом деле не запущен (поставьте там точку останова, чтобы убедиться, что это действительно так), либо (б) есть проблема с синхронизацией, на которую полагается updateDisplay. Убедитесь, что в этом методе нет ничего nil в тот момент, когда вы его достигли (что, вероятно, немного отличается от времени для этих двух подходов). «Ничего не делает» в ObjC 90% времени означает «что-то ноль». В 9% случаев это означает «вы на самом деле не называли то, что, как вы думали, сделали», а в 1% - что-то другое.

Rob Napier 10.08.2018 17:11

Хороший отзыв от @particleman. Если это выполняется в основном потоке, тогда это блокирует основной поток, и это резко изменит тайминги (и это незаконно, но все же это может произойти)

Rob Napier 10.08.2018 17:13

К сожалению, ничего не равно нулю, все журналы верны, все значения совпадают, но пользовательский интерфейс по-прежнему не обновляется ;-( Я проверю, является ли время проблемой, спасибо за эту идею!

Nanunana 10.08.2018 17:18

Я думаю, что запуск кода семафора в основном потоке может привести меня к решению. Большое спасибо за этот намек, я почему-то об этом не подумал. Все еще не уверен, почему это вызывает эту проблему, но я выясню это в понедельник ;-)

Nanunana 10.08.2018 17:54
0
4
57
0

Другие вопросы по теме