2009-08-07 12 views
6

Tengo un problema con NSOperation y observador.NSOperation, observer and thread error

Tengo tabbarcontroller y splashController. Quiero que la pantalla secundaria se cargue y descargue el archivo, y cuando se descargue el archivo, haga que aparezca tabbarcontroller en la pantalla.

El problema es que he un error:

_WebTryThreadLock bool (bool), 0x3d2fa90: tratado de obtener bloquear la web de un hilo distinto del hilo principal o el hilo web. Esto puede ser el resultado de llamar a UIKit desde un hilo secundario. Estrellarse ahora ...

Este es mi código:

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

} 

Podría alguien ayudarme?

Respuesta

20

Las notificaciones de observación del valor clave se producen en el mismo subproceso en el que se cambió la propiedad observada. Manzana menciona la siguiente advertencia en la referencia de clase NSOperation:

"A pesar de que se puede adjuntar observadores a estas propiedades, no se debe utilizar fijaciones de cacao para unirse a elementos de interfaz de usuario Código de la aplicación asociados con la interfaz de usuario. normalmente debe ejecutarse solo en el hilo principal de su aplicación. Debido a que una operación puede ejecutarse en cualquier hilo, cualquier notificación KVO asociada con esa operación puede ocurrir de manera similar en cualquier hilo. "

En su método observeValueForKeyPath:ofObject:change:context:, debe realizar cualquier operación de UIKit en el hilo principal. Dado que está realizando varios pasos allí, es posible que desee crear otro método en su clase de observación llamada -dataLoadingFinished al que puede llamar en el hilo principal desde el interior observe:…. A continuación, puede incluir la totalidad de su interfaz de usuario llama allí, en lugar de tener que llamar performSelectorOnMainThread para cada uno:

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

Incluso en los casos en que el roscado no es un problema, se acostumbra a definir métodos distintos para aplicar en la práctica cada uno acción de observación, para evitar que el observe:… crezca demasiado.

También tenga en cuenta que, aunque solo está observando una propiedad, es una mejor práctica validar que la propiedad que le interesa es la que solicita la notificación de cambio. Consulte el artículo de Dave Dribin Proper KVO Usage para conocer la mejor manera de hacerlo.