Проблема синхронизации NSOperation - PullRequest
2 голосов
/ 16 октября 2010

Я изо всех сил пытаюсь найти способ синхронизировать работу в приложении для iPhone. У меня есть три основных NSOperation.

    NSInvocationOperation *showSpinner = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(spinnerOn:) object:YES];
    NSInvocationOperation *reloadDatasource = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(reloadDatasource) object:nil];
    NSInvocationOperation *hideSpinner = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(spinnerOn:) object:NO];
    // Add dependency
    [reloadDatasource addDependency:showSpinner];
    [hideSpinner addDependency:reloadDatasource];

    [self.queue addOperation:showSpinner];
    [self.queue addOperation:reloadDatasource];
    [self.queue addOperation:hideSpinner];

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

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

Я понял, что изменения на графической стороне происходят в основном потоке. Поэтому я спрашиваю, как я могу изменить код, чтобы сделать то, что он должен делать. Что: создать счетчик, загрузить данные и удалить счетчик? Есть ли общий способ разделения графической операции и операции с данными? Например создать две разные операции.

спасибо

Ответы [ 3 ]

1 голос
/ 16 октября 2010

Как насчет письма

[self spinnerOn:YES];
[self performSelectorInBackground:@selector(reloadDatasource) withObject:nil];

и затем перезвоните вашему основному потоку в методе 'reloadDataSource' с

[self performSelectorInMainThread:@selector(spinnerOn:) withObject:NO];
0 голосов
/ 18 октября 2010

В вашем методе spinnerOn: вы можете попробовать добавить немного логики, чтобы убедиться, что операция происходит в главном потоке?

if ( ![NSThread isMainThread] ) { 
    [self performSelectorOnMainThread:@selector(spinnerOn:) withObject:anObject waitUntilDone:NO];
    return;
}

Мне было бы интересно посмотретьесли это имеет значение.Я подозреваю, что если вы вызываете задачу пользовательского интерфейса из альтернативного потока, они встают в очередь и могут в конечном итоге произойти сразу, в неопределенное время в главном потоке.

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

[self.queue setMaxConcurrentOperationCount: 1];

Дайте мне знать, если это вообще полезно.

0 голосов
/ 16 октября 2010

Обязательно ли использовать NSOperation? Если нет, то я думаю, что вы выбираете сложный способ решения простой проблемы, используйте делегат NSConnection (или что-то подобное, поскольку я не уверен, что делает ваш reloadDataSource), чтобы запустить и остановить спиннер, а затем вы сделанный.

...