Как обновить интерфейс в блоке завершения задачи? - PullRequest
4 голосов
/ 26 августа 2011

В моем приложении я позволяю индикатору прогресса запустить анимацию перед отправкой HTTP-запроса.Обработчик завершения определяется в блоке.Получив данные ответа, я скрываю индикатор прогресса изнутри блока.Мой вопрос, как я знаю, обновления пользовательского интерфейса должны выполняться в основном потоке.Как я могу убедиться в этом?

Если я определяю метод в контроллере окна, который обновляет пользовательский интерфейс, и позволяет блоку вызывать метод вместо непосредственного обновления пользовательского интерфейса, это решение?

Ответы [ 2 ]

10 голосов
/ 27 августа 2011

Кроме того, если ваше приложение предназначено для iOS> = 4, вы можете использовать Grand Central Dispatch:

dispatch_async(dispatch_get_main_queue(), ^{
    // This block will be executed asynchronously on the main thread.
});

Это полезно, когда ваша пользовательская логика не может быть легко выражена с помощью одного селектора и аргументов объекта, которые принимают методы performSelect….

Чтобы выполнить блок синхронно, используйте dispatch_sync() - но убедитесь, что вы не выполняете его в основной очереди, иначе GCD заблокируется.

__block NSInteger alertResult; // The __block modifier makes alertResult writable
                               // from a referencing block.
void (^ getResponse)() = ^{
    NSAlert *alert = …;
    alertResult = [NSAlert runModal];
};

if ([NSThread isMainThread]) {
    // We're currently executing on the main thread.
    // We can execute the block directly.
    getResponse();
} else {
    dispatch_sync(dispatch_get_main_queue(), getResponse);
}

// Check the user response.
if (alertResult == …) {
    …
}
0 голосов
/ 26 августа 2011

Вы, наверное, что-то не так поняли. Использование блоков не означает, что ваш код выполняется в фоновом потоке. Есть много плагинов, которые работают асинхронно (в другом потоке) и используют блоки.

Есть несколько вариантов решения вашей проблемы.

Вы можете проверить, работает ли ваш код в главном потоке, используя [NSThread isMainThread]. Это поможет вам убедиться, что вы не на заднем плане.

Вы также можете выполнять действия в основном или фоновом режиме, используя performSelectorInMainThread:SEL или performSelectorInBackground:SEL.

Приложение сразу падает, когда вы пытаетесь вызвать пользовательский интерфейс из потока bakcground, поэтому довольно легко найти ошибку.

...