NSOperation, наблюдатель и ошибка потока - PullRequest
6 голосов
/ 07 августа 2009

У меня проблема с NSOperation и наблюдателем.

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

Проблема в том, что у меня ошибка:

bool _WebTryThreadLock (bool), 0x3d2fa90: попытался получить веб-блокировку из потока, отличного от основного потока или веб-потока. Это может быть результатом обращения к UIKit из вторичного потока. грохот сейчас ...

Это мой код:

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    queue = [[NSOperationQueue alloc] init];


    NSString *path = [NSString stringWithFormat:@"%@flux.xml",DOCPATH];
    //Le fichier existe dans le repertoire des documents
    if([[NSFileManager defaultManager] fileExistsAtPath:path])
        [window addSubview:tabBarController.view];
    else
    {
        splash = [[SplashController alloc] init];
        [window addSubview:splash.view];
    }

    DataLoadOperation *operation = [[DataLoadOperation alloc] initWithURL:[NSURL URLWithString:@"http://sly.33.free.fr/flux.xml"]];
    [self.queue addOperation:operation];
    [operation addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:nil];


}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];
    NSLog(@"fini");

}

Может ли кто-нибудь мне помочь?

1 Ответ

20 голосов
/ 07 августа 2009

Уведомления наблюдения значения ключа происходят в том же потоке, в котором наблюдалось изменение свойства. Apple упоминает следующее предупреждение в описании класса NSOperation:

"Хотя вы можете присоединять наблюдателей к этим свойствам, вы не должны использовать привязки Какао для привязки их к элементам пользовательского интерфейса вашего приложения. Код, связанный с вашим пользовательским интерфейсом, обычно должен выполняться только в главном потоке вашего приложения. Поскольку операция может выполнить в любом потоке, любые уведомления KVO, связанные с этой операцией, могут аналогичным образом появляться в любом потоке. "

В вашем методе observeValueForKeyPath:ofObject:change:context: вы должны выполнять любые операции UIKit в главном потоке. Поскольку вы выполняете несколько шагов, вы можете создать другой метод в своем классе наблюдения с именем -dataLoadingFinished, который можно вызывать в главном потоке изнутри observe:…. После этого вы можете включить все свои вызовы пользовательского интерфейса вместо того, чтобы вызывать performSelectorOnMainThread для каждого:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
  [self performSelectorOnMainThread:@selector(dataLoadingFinished:) withObject:nil waitUntilDone:YES];
}

Даже в тех случаях, когда многопоточность не является проблемой, принято определять отдельные методы для фактической реализации каждого действия наблюдения, чтобы предотвратить слишком большое увеличение observe:….

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...