2009-08-07 9 views
6

Ho un problema con NSOperation e osservatore.Errore NSOpertura, osservatore e thread

Ho un tabbarcontroller e un splashController. Voglio caricare lo splashscreen e scaricare il file e quando il file è scaricato fai apparire sullo schermo il tabbarcontroller.

Il problema è che 'ho un errore:

bool _WebTryThreadLock (bool), 0x3d2fa90: cercato di ottenere bloccare il web da un thread diverso dal thread principale o il filo web. Questo può essere un risultato di chiamare a UIKit da un thread secondario. Crashing ora ...

Questo è il mio codice:

- (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"); 

} 

Qualcuno mi potrebbe aiutare?

risposta

20

Le notifiche di osservazione dei valori-chiave si verificano sullo stesso thread in cui è stata modificata la proprietà osservata. Apple ha menziona il seguente avviso nel riferimento di classe NSOperation:

"Anche se è possibile allegare osservatori a queste proprietà, non si dovrebbe usare attacchi Cocoa per legarli agli elementi di interfaccia utente codice dell'applicazione associati con l'interfaccia utente. in genere deve essere eseguito solo nel thread principale dell'applicazione. Poiché un'operazione può essere eseguita in qualsiasi thread, qualsiasi notifica KVO associata a tale operazione potrebbe verificarsi in modo simile in qualsiasi thread. "

Nel metodo observeValueForKeyPath:ofObject:change:context:, è necessario eseguire qualsiasi operazione UIKit sul thread principale. Poiché stai eseguendo più passaggi, potresti voler creare un altro metodo nella classe di osservazione chiamata -dataLoadingFinished che puoi chiamare sul thread principale all'interno di observe:…. È quindi possibile includere tutti l'interfaccia utente chiamate in là, invece di dover chiamare performSelectorOnMainThread per ciascuno di essi:

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

Anche nei casi in cui threading non è un problema, si è soliti definire metodi separati per implementare in realtà ogni azione di osservazione, per evitare che lo observe:… cresca troppo.

Si noti inoltre che anche se si sta osservando solo una proprietà, è comunque consigliabile convalidare che la proprietà a cui si è interessati è quella che richiede la notifica di modifica. Vedere l'articolo di Dave Dribin Proper KVO Usage per il modo migliore in cui farlo.

Problemi correlati