Самый быстрый способ закрыть UIPopoverController?

Я отправляю уведомление из UIPopoverController обратно в свое основное представление, которое затем немедленно вызывает уволитьPopoverAnimated, а затем выполняет довольно тяжелую работу по загрузке веб-представлений. Весь этот код работает; проблема в том, что на некоторых старых iPad всплывающее окно фактически не закрывается до тех пор, пока не будет завершена интенсивная работа процессора (проверено в отладчике). Это приводит к тому, что всплывающее окно зависает на секунду после закрытия. Как я могу обеспечить немедленное отклонение всплывающего окна вместо того, чтобы сначала выполнять интенсивный код?

Метод, который отвечает на уведомление, выглядит следующим образом:

- (void)changeDefaultView:(NSNotification *)note
{
    [self closePopover];

    int i;
    for(i = 0; i < [arrWebViewControllers count]; i++)
    {
        WebViewController *wvc = [arrWebViewControllers objectAtIndex:i];
        [[wvc webview] stopLoading];
        [[wvc webview] removeFromSuperview];
        [[wvc imageview] removeFromSuperview];
        wvc = nil;
    }

    [arrWebViewControllers removeAllObjects];
    [arrLinks removeAllObjects];
    [arrImageViews removeAllObjects];

    [self loadCategory:[note object]];

    [self addWidgetsToView];
}

и closePopover:

- (void)closePopover
{
    if(popover != nil)
    {
        [popover dismissPopoverAnimated:YES];
        popover = nil;
    }
}

person Shteven W    schedule 12.09.2012    source источник


Ответы (1)


Анимация исчезающего всплывающего окна происходит в основном цикле выполнения; если вы выполняете тяжелую работу ЦП в основном потоке, цикл не сможет запуститься. Итак, что вам нужно сделать, это выполнить свою работу в фоновом потоке.

В настоящее время предпочтительным способом сделать это является использование Grand Central Dispatch, например: (я предполагаю, что loadCategory: является операцией с интенсивным использованием ЦП)

- (void)changeDefaultView:(NSNotification *)note
{
    [self closePopover];

    int i;
    for(i = 0; i < [arrWebViewControllers count]; i++)
    {
        WebViewController *wvc = [arrWebViewControllers objectAtIndex:i];
        [[wvc webview] stopLoading];
        [[wvc webview] removeFromSuperview];
        [[wvc imageview] removeFromSuperview];
        wvc = nil;
    }

    [arrWebViewControllers removeAllObjects];
    [arrLinks removeAllObjects];
    [arrImageViews removeAllObjects];

    // perform the expensive operation on a background thread
    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        [self loadCategory:[note object]];

        // now get back onto the main thread to perform our UI update
        dispatch_async(dispatch_get_main_queue(), ^{

            [self addWidgetsToView];

        });

    });
}
person Simon    schedule 12.09.2012
comment
Спасибо, это должно очень помочь - я мог бы также добавить addWidgets в блок, я скоро поэкспериментирую с этим. - person Shteven W; 12.09.2012
comment
предполагая, что addWidgetsToView добавляет что-либо к вашему представлению, вам нужно поместить это в основную очередь. - person Simon; 12.09.2012
comment
Да, я пытался, и он потерпел крах, но все же это был хороший урок, который можно увидеть из первых рук. Единственное изменение по сравнению с вашим кодом заключалось в том, что я также поместил объекты цикла for/remove в фоновый поток, и теперь он отлично работает. Еще раз спасибо! - person Shteven W; 12.09.2012