NSOperationQueue, кажется, зависает после завершения на несколько секунд

У меня есть собственный контроллер представления, который реализует протоколы from 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 секунд, а затем, наконец, следует представление со скрытым индикатором.

Любые идеи?


person Ben Collins    schedule 30.06.2010    source источник
comment
Вы вызываете hideActivityIndicators в основном потоке?   -  person falconcreek    schedule 30.06.2010
comment
@falconcreek: нет; нужно ли мне? (см. редактирование для лучшей картины того, что происходит)   -  person Ben Collins    schedule 30.06.2010


Ответы (1)


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

- (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];
}

ИЗМЕНИТЬ"

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

Пример проекта TopSongs прекрасно это демонстрирует. Оператор переадресации в основной поток основан на коде в файле AppDelegate.m в образце.

person falconcreek    schedule 30.06.2010
comment
Да, это было проблемой. Однако теперь мне любопытно: если все обновления пользовательского интерфейса должны выполняться в основном потоке, почему бы им просто не генерировать исключение? Почему они выполняются как положено, а просто задерживаются на 5 с? - person Ben Collins; 30.06.2010
comment
По сути, представления не перерисовывались, чтобы соответствовать изменениям состояния, выполненным для объектов представления из другого потока, до тех пор, пока цикл выполнения для другого потока не был разорван. Не исключение, а проблема параллелизма. Подробнее здесь developer.apple.com/iphone /библиотека/документация/какао/ - person falconcreek; 01.07.2010