it-swarm.com.ru

В чем разница между executeSelectorOnMainThread и dispatch_async в основной очереди?

У меня были проблемы с изменением представления внутри потока. Я попытался добавить подпредставление, но для отображения потребовалось около 6 или более секунд. Я наконец получил это, но я не знаю как именно. Поэтому мне было интересно, почему это работает и в чем разница между следующими методами:

//this worked -added the view instantly
dispatch_async(dispatch_get_main_queue(), ^{
    //some UI methods ej
    [view addSubview: otherView];
}

//this took around 6 or more seconds to display
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView
 waitUntilDone:NO];

//Also didnt work: NSNotification methods -  took also around 6 seconds to display
//the observer was in the viewController I wanted to modify
//paired to a method to add a subview.
[[NSNotificationCenter defaultCenter] postNotificationName:
 @"notification-identifier" object:object];

Для справки это было вызвано внутри этого обработчика завершения класса ACAccountStore.

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) {
            if(granted) {
            //my methods were here
            }
}

Правка: Когда я сказал, что это не сработало, я имел в виду, что потребовалось около 6 секунд, чтобы отобразить вид, который я добавил. 

52
Miguel Lomelí

По умолчанию -performSelectorOnMainThread:withObject:waitUntilDone: только запланирует запуск селектора в режиме цикла выполнения по умолчанию. Если цикл выполнения находится в другом режиме (например, в режиме отслеживания), он не будет работать, пока цикл выполнения не переключится обратно в режим по умолчанию. Вы можете обойти это с помощью варианта -performSelectorOnMainThread:withObject:waitUntilDone:modes: (передав все режимы, в которых вы хотите, чтобы он работал).

С другой стороны, dispatch_async(dispatch_get_main_queue(), ^{ ... }) запустит блок, как только главный цикл выполнения вернет поток управления обратно в цикл событий. Это не заботится о режимах. Так что если вы не хотите заботиться о режимах, лучше использовать dispatch_async().

70
Lily Ballard

Скорее всего, потому что performSelectorOnMainThread:withObject:waitUntilDone: ставит в очередь сообщения с обычными режимами цикла выполнения. Согласно Apple Concurrency Programming Guide , основная очередь будет чередовать поставленные в очередь задачи с другими событиями из цикла выполнения приложения. Таким образом, если есть другие события, которые должны быть обработаны в очереди событий, блоки очереди в очереди отправки могут быть запущены первыми, даже если они были отправлены позже.

Эта статья является превосходным объяснением performSelectorOnMainThread против dispatch_async, которая также отвечает на поставленный выше вопрос.

1
Say2Manuj

Вы пробовали PerformSelectorOnMainThread с waitUntilDone=YES

Например: 

Код:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES];

Я думаю, что это может решить проблему, поскольку PerformSelectorOnMainThread так долго реагирует.

0
Ruchira Randana