2013-05-04 5 views
4

NSOperation 하위 클래스에서 작업 중이며 완료 블록이 두 번 연속 호출되는 매우 이상한 문제가 발생했습니다. KVO 호출은 괜찮아 보이지만 completionBlock은 여전히 ​​이상하게 두 번 호출됩니다. NSOperation을 오해하고 있습니까? 나는 단순히이 같은 completionBlock 설정NSOperation 완료 블록이 두 번 호출됩니다.

- (void)main { 
    @autoreleasepool { 
     [self willChangeValueForKey:@"isExecuting"]; 
     [self willChangeValueForKey:@"isReady"]; 
     executing = YES; 
     [self didChangeValueForKey:@"isReady"]; 
     [self didChangeValueForKey:@"isExecuting"]; 

     //start the operation 
    } 
} 

:

self.completionBlock = ^{ 
    NSLog(@"Completed"); 
} 

는이 방법을 완료 문서는 완료 블록이 isFinishedYES이되면라는 것을 단지 내 코드에서 한 번 발생되는 것을 말한다 가 호출됩니다. (그냥 한 번 호출됩니다, 나는 그것을 두 번 확인했습니다)

- (void)completeOperation { 
    [self willChangeValueForKey:@"isExecuting"]; 
    [self willChangeValueForKey:@"isFinished"]; 
    executing = NO; 
    completed = YES; 
    [self didChangeValueForKey:@"isExecuting"]; 
    [self didChangeValueForKey:@"isFinished"]; 
} 

그러나 completionBlock이 호출됩니다. 콘솔에 "Completed"를 두 번 인쇄합니다.

그리고 여기에 현재 상태를 나타내는 방법이다 : 그것의 원인이 될 수없는, 그래서

- (BOOL)isReady { 
    if (executing || cancelled || completed) { 
     return NO; 
    } 
    return YES; 
} 
- (BOOL)isCancelled { 
    return cancelled; 
} 

- (BOOL)isConcurrent { 
    return YES; 
} 

- (BOOL)isExecuting { 
    return executing; 
} 

- (BOOL)isFinished { 
    return completed; 
} 

isCancelled 결코 내 테스트 코드 YES으로 변합니다.

나는 실제로 completionBlock이 두 번 호출되는 이유를 얻지 못합니다. 완료 블록을 완료 블록 내에서 nil로 설정하는 경우조차도 두 번 더 낯선 사람이라고도합니다.

답변

4

이것이 원인인지는 모르겠지만 경험상 읽기 전용 상태 속성을 재정의 할 필요는 없습니다. 당신은 메인 루프에서 주기적으로 isCancelled를 체크 할 책임이 있으며, 당신이하고있는 일에서 무엇이든지 빠져 나오기를 원한다면,하지만 다른 상태 플래그 (isReady, isFinished, isExecuting)는 자동으로 처리됩니다.

상태 플래그 처리를 제거하고 -main에서 처리하는 횟수는 얼마나됩니까?

편집 : 당신은 그것의 모습으로 노트를 통해 in the docs

을 읽어야합니다, 당신은 동시성을 허용하는 플래그를 무시하는 가정하면, isReady 또는 isCancelled을 무시하고 대신에 따라 -start 오버라이드 (override) 할 필요가 없습니다한다 문서의 지침

+0

네가 맞아! 이전에는 문서를 잘못 읽었을 것입니다. 이제 시작 단계에서 사용자 정의 백그라운드 스레드를 시작하고 isReady 및 isCancelled 대체를 제거 했으므로 이제 완료 블록은 한 번만 호출됩니다. – JonasG

+0

사용자가 자신의'isReady '또는'isCancelled' 메소드를 호출합니다. 커스텀'isReady'가 필요하다면, 당신은'super'를 호출해야합니다 : 문서가 말하듯이, "사용자 정의 조건을 사용하여 조작 객체의 준비 상태를 결정하려면,이 메소드를 오버라이드하고 정확하게 반영하는 값을 리턴 할 수 있습니다 수신기의 준비 여부를 결정합니다. 사용자 정의 구현에서는 super를 호출하고 객체의 준비 상태에 반환 값을 통합해야합니다. 사용자 정의 구현은 isReady 키 경로에 대한 적절한 KVO 알림을 생성해야합니다. " – Rob

관련 문제