NSOperationQueue, кажется, зависает при завершении в течение нескольких секунд - PullRequest
1 голос
/ 30 июня 2010

У меня есть собственный контроллер представления, который реализует протоколы от UITableViewDataSource и UITableViewDelegate. Когда я загружаю данные для своей таблицы (в моем методе viewDidLoad), я создаю NSOperationQueue и NSInvocationOperation и добавляю их в очередь. Я подбрасываю индикатор активности, и viewDidLoad выходит.

Метод, используемый для операции, завершает анимацию индикатора активности.

Я заметил, что, когда операция завершается, перед тем, как операция действительно завершится, наступает пауза в 5-7 секунд, хотя NSLog выглядит как возвращенный метод операции.

Я пытался использовать инструменты, чтобы выяснить, где происходит пауза, но я не могу сказать из этого, потому что большая часть моего процессорного времени расходуется в системных библиотеках.

Редактировать Вот сокращенная версия:

@implementation MyViewController
@synthesize ...

- (void)viewDidLoad {
    [super viewDidLoad];
    self.opsQueue = [[NSOperationQueue alloc] init];

    NSInvocationOperation *aiStartOp = [[[NSInvocationOperation alloc]
                                           initWithTarget:self
                                                 selector:@selector(showActivityIndicators)
                                                   object:nil] autorelease];
    [self.opsQueue addOperation:aiStartOp];

    NSInvocationOperation *dataOp = [[[[NSInvicationOperation alloc] 
                                         initWithTarget:self
                                               selector:@selector(dataUpdate)
                                                 object:nil] autorelease];
    [dataOp addDependency aiStartOp];
    [self.opsQueue addOperation:dataOp];

    NSInvicationOperation *aiStopOp = [[[NSInvicationOperation alloc]
                                          initWithTarget:self
                                                selector:@selector(hideActivityIndicators)
                                                  object:nil] autorelease];
    [aiStopOp addDependency:dataOp];
    [self.opsQueue addOperation:aiStopOp];
}

/* other stuff */

@end

Просто чтобы прояснить, последняя операция в очереди такая:

- (void)hideActivityIndicators {
    DLog(@"hiding activity indicator");
    self.portraitChartProgressView.hidden = YES;
    [self.portraitChartProgressIndicator stopAnimating];

    self.landscapeProgressView.hidden = NO;
    [self.landscapeProgressIndicator startAnimating];
}

То, что я вижу в журнале, - это вывод вышеуказанного сообщения журнала, за которым следует пауза в 5 секунд, а затем, наконец, вид с скрытым индикатором.

Есть идеи?

1 Ответ

3 голосов
/ 30 июня 2010

Все события пользовательского интерфейса, рисование и т. Д. Должны выполняться в главном потоке.Вы можете переадресовывать вызовы в основной поток, используя что-то вроде следующего:

- (void)hideActivityIndicators {

    if (![NSThread isMainThread]) 
         [self performSelectorOnMainThread:@selector(hideActivityIndicators) withObject:nil waitUntilDone:NO];

    DLog(@"hiding activity indicator");
    self.portraitChartProgressView.hidden = YES;
    [self.portraitChartProgressIndicator stopAnimating];

    self.landscapeProgressView.hidden = NO;
    [self.landscapeProgressIndicator startAnimating];
}

EDIT "

Теперь, когда я выгляжу немного более тщательно, одна вещь, которую вы, вероятно,не нужно запускать и останавливать «загрузку» представлений, добавляя к NSOperationQueue. Вероятно, единственное, что вам нужно сделать в очереди, - это обновление данных, затем отправка уведомлений и делегирование для обновления ваших представлений.когда операция с данными завершена.

Пример проекта TopSongs очень хорошо демонстрирует это. Оператор перенаправления в основной поток основан на коде в файле AppDelegate.m в примере.

...