2009-08-07 7 views
6

NSOperation과 observer에 문제가 있습니다.NSOperation, observer 및 thread error

저는 tabbarcontrollersplashController입니다. 스플래시 화면을로드하고 파일을 다운로드하려면 파일을 다운로드 할 때 tabbarcontroller을 화면에 표시하십시오.

부울 _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"); 

} 

이 사람이 나를 도울 수 있을까요?

답변

20

키 - 값 관찰 알림은 관찰 된 속성이 변경된 동일한 스레드에서 발생합니다. 애플은 NSOperation 클래스 참조 다음과 같은 경고가 언급 :

"이러한 속성에 관찰자를 첨부 할 수 있지만, 당신은 당신의 사용자 인터페이스와 관련된 응용 프로그램의 사용자 인터페이스 코드의 요소를 결합하는 코코아 바인딩을 사용하지 않아야합니다. 일반적으로 응용 프로그램의 주 스레드에서만 실행해야합니다. 작업이 모든 스레드에서 실행될 수 있기 때문에 해당 작업과 관련된 모든 KVO 알림은 모든 스레드에서 유사하게 발생할 수 있습니다. "

observeValueForKeyPath:ofObject:change:context: 메서드에서 주 스레드에서 모든 UIKit 작업을 수행해야합니다. 거기에서 여러 단계를 수행하기 때문에 실제로 관찰 클래스에 -dataLoadingFinished이라는 또 다른 메서드를 만들 수 있습니다.이 메서드는 observe:… 내부의 주 스레드에서 호출 할 수 있습니다. 당신은 다음 UI의 모든 오히려 각각에 대해 performSelectorOnMainThread를 호출하는 것보다, 거기에 호출을 포함 할 수 있습니다 스레딩 문제가되지 않는 경우에도 경우에

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

, 실제로 각을 구현하기위한 별도의 방법을 정의하는 관례 관찰 작업을 수행하여 observe:…이 너무 커지지 않도록하십시오.

하나의 속성 만 관찰 중이더라도 관심있는 속성이 변경 알림을 요구하는지 확인하는 것이 좋습니다. 이 작업을 수행하는 가장 좋은 방법은 Dave Dribin의 기사 Proper KVO Usage을 참조하십시오.