Подтвердить что ты не робот

Какая разница между performSelectorOnMainThread и dispatch_async в главной очереди?

У меня возникли проблемы с изменением вида внутри потока. Я попытался добавить subview, но для отображения потребовалось около 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];

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

Вы пробовали PerformSelectorOnMainThread с помощью waitUntilDone=YES

Например:

Код:

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

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