2009-08-07 22 views
6

Mam problem z NSOperation i obserwatorem.Błąd połączenia, obserwatora i wątku

Mam tabbarcontroller i splashController. Chcę załadować zawartość ekranu startowego i pobrać plik, a gdy plik zostanie pobrany, wyświetl ekran tabbarcontroller.

Problemem jest to, że „ve błąd:

BOOL _WebTryThreadLock (bool), 0x3d2fa90: próbował uzyskać zablokowanie wstęga z gwintem innych niż główny przewlekanie nitki internetowej. Może to być być wynikiem wywołania UIKit z wątku dodatkowego. Upaść teraz ...

To jest mój kod:

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

} 

Czy ktoś może mi pomóc?

Odpowiedz

20

Notatki obserwujące wartości klucz-wartość występują w tym samym wątku, w którym obserwowana właściwość została zmieniona. Jabłko wymienia następujące ostrzeżenie w odniesieniu klasy NSOperation:

„Chociaż można dołączyć obserwatorów do tych właściwości, nie należy używać powiązań kakao związać je do elementów interfejsu użytkownika kodzie aplikacji związanych z interfejsem użytkownika. zazwyczaj musi być wykonywane tylko w głównym wątku aplikacji, ponieważ operacja może być wykonywana w dowolnym wątku, wszystkie powiadomienia KVO powiązane z tą operacją mogą podobnie występować w dowolnym wątku. "

W swojej metodzie observeValueForKeyPath:ofObject:change:context: należy wykonać operacje UIKit na głównym wątku. Ponieważ wykonujesz tam wiele kroków, możesz chcieć stworzyć inną metodę w klasie obserwacyjnej o nazwie -dataLoadingFinished, którą możesz wywołać w głównym wątku z poziomu observe:…. Następnie można zawierać wszystkie swoje UI nazywa się tam, zamiast zadzwonić performSelectorOnMainThread dla każdego z nich:

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

Nawet w przypadkach, gdzie gwintowanie nie jest problem, to jest w zwyczaju, aby zdefiniować osobne metody rzeczywiście wdrożyć każdy działanie obserwacyjne, aby zapobiec zbyt dużemu wzrostowi.

Należy również pamiętać, że nawet jeśli obserwuje się tylko jedną właściwość, nadal należy sprawdzać, czy właściwość, którą Państwo interesują, jest tą, która powoduje powiadomienie o zmianie. Zobacz artykuł Dave'a Dribina o numerze Proper KVO Usage, aby uzyskać najlepszy sposób na zrobienie tego.

Powiązane problemy