Дождитесь завершения выбора фона для вызова нового метода

Я пытаюсь выполнить сбор данных из интернета под нагрузкой. Чтобы не отставать от пользовательского интерфейса, я выполняю загрузку и анализ HTML с помощью

[self performSelectorInBackground:@selector(alertThreadMethod) withObject:nil];

который проверяет, есть ли предупреждение онлайн. Однако для отображения информации в представлении iOS говорит, что мне нужно использовать основной поток. Поэтому я вызываю код дисплея сразу после:

[self performSelectorInBackground:@selector(alertThreadMethod) withObject:nil];
[self loadAlert];

При этом, [self loadAlert]; на самом деле работает перед селектором в фоновом режиме (это быстрее). Из-за этого у него нет информации, которую должен предоставлять селектор в фоновом режиме.

Как я могу гарантировать, что [self loadAlert]; бежит после? Или есть лучший способ сделать это?

2 ответа

Решение

Вы можете переместить вызов loadAlert в alertThreadMethod или использовать последовательные очереди Grand Central Dispatch, например,

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
    [self alertThreadMethod];
    [self loadAlert];
});
dispatch_release(queue);

Или, если loadAlert обновляет пользовательский интерфейс, так как вы делаете обновления пользовательского интерфейса в основной очереди, вы должны сделать что-то вроде:

dispatch_queue_t queue = dispatch_queue_create("com.example.MyQueue", NULL);
dispatch_async(queue, ^{
    [self alertThreadMethod];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self loadAlert];
    });
});
dispatch_release(queue);

Кстати, если вы просто выполняете эту одну задачу в фоновом режиме, а не создаете свою собственную последовательную очередь, вы можете просто использовать одну из существующих фоновых очередей. Вам нужно создать очередь только в том случае, если вам нужен последовательный характер (т. Е. У вас будет много вызовов dispatch_async, и вы не сможете одновременно их запускать). Но в этом простом случае это может быть даже немного более эффективно, минуя создание и освобождение последовательной очереди:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
    [self alertThreadMethod];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self loadAlert];
    });
});

В вашем alertThreadMethod после получения информации вызовите метод executeSelectorOnMainThread:withObject:waitUntilDone: и передайте ему селектор в свой метод loadAlert.

-(void)alertThreadMethod
{
   // get your information here

   performSelectorOnMainThread:@selector(loadAlert) withObject:nil waitUntilDone:NO
}
Другие вопросы по тегам