2

그물에 다른 곳에서 답변을 찾을 수 없으므로 도움을 얻을 수있었습니다.NSOperation 하위 클래스의 performSelector

NSInvocation과 같은 구체적인 하위 클래스로는 이해할 수없는 NSOperation 작업의 결과를 검색 할 수있는 시스템을 만들려고합니다.

나는 규칙에 의해 추상적이고 실행 코드의 신체를 포함하는 함수 -main을 구현하기 위해 확장해야하는 NSOperation 하위 클래스 ( TheEngine)이있다.

TheEngine는 그의 작업 선택기가 속한 theSelectortheObject주의하는 것입니다 다음 초기화 기능이 포함되어 있습니다. 내 observeValueForKeyPath:ofObject:change:context: 기능에

-(id)initWithCallbackSelector:(SEL)theSelector inObject:(id)theObject 

난과 같이 콜백 함수를 호출하고 싶습니다 :

NSLog(@"Some debug text to ensure this function is being called", nil); 
[theObject performSelector:theSelector withObject:someData afterDelay:0]; 

전체 프로세스는 다음과 같이 간다 : 그것은 또한 재산 isFinished에 대한 KV 관찰자를 등록

aViewController이 확장되어 확장 됨 TheEngine - 할 수 있습니다. Task을 호출하고 작업 대기열에 추가합니다.

TheTask* TT = [[TheTask alloc] initWithCallbackSelector: 
    @selector(resultHandler:) inObject:theObject]; 

모든 오류 또는 예외없이 예상대로 실행되는 것으로 보입니다. 그러나 실행이 observeValueForKeyPath:ofObject:change:context:에 도달하면 콜백이 실제로 호출되지 않습니다. 나는 Obj-C에 익숙하지 않기 때문에이 유형의 스레딩에 대한 나의 이해가 맞는지 확실하지 않다.

-(id)initWithCallbackSelector:(SEL)theSelector inObject:(id)theObject{ 

    if([self init]){ 

     self.selectorsParentObject  = theObject; 
     self.selectorToCallWhenFinished = theSelector; 


     [self addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:NULL]; 

     return self; 
    } 

    return nil; 
} 


-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)theObject change:(NSDictionary*)theChange context:(void*)theContext{ 

    if([keyPath isEqualToString:@"isFinished"]){ 

     NSLog(@"activity is finished with change: %@", theChange); 

     NSLog(@"target object: %@", self.selectorsParentObject); 
     NSLog(@"target selector: %@", NSStringFromSelector(self.selectorToCallWhenFinished)); 

     //[self performSelectorOnMainThread:self.selectorToCallWhenFinished withObject:self.resultData waitUntilDone:NO]; 
     [self.selectorsParentObject performSelector:@selector(selectorToCallWhenFinished) withObject:self.resultData afterDelay:0]; 
    } 
} 

이 어떤 도움을 감사 :

여기에 전체 코드입니다!

답변

1

NSOperation은 백그라운드 스레드에서 실행될 가능성이 큽니다. 해당 스레드가 사라지거나 해당 스레드가 실행 루프를 펌프하지 못하면 performSelector:withObject:afterDelay:에 대한 호출이 실행되지 않습니다. performSelectorOnMainThread:...에 전화를 받았다고했습니다. 이게 효과가 있었나요?

메인 스레드에서 실행하거나 performSelector:withObject: (afterDelay: 제외)으로 실행해야합니다. performSelector:withObject:에는 실행 루프가 필요하지 않습니다. 선택기 [self performSelectorOnMainThread:@selector(runCallback) withObject:nil waitUntilDone:NO];와 주 스레드에서 해고되었다 있도록 롭 제안으로 전화를 observeValueForKeyPath:ofObject:change:context:

이었다로

+0

팁 주셔서 감사합니다, 당신의 직감 올바른 밝혀졌다 - 내가 만든 변경 사항을 게시 할 것입니다 :) – aktar

0

, 코드, 백그라운드 스레드에서 실행 된 나는 처음에 코드를 변경했다.

그러나 주 스레드가 TheTask로 밝혀 예외가 theSelector을 보유하고 있지 않습니다 TheTask로 던져진이 경우

.이 문제를 해결하려면, 나는 추가 기능 -runCallback를 작성

-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)theObject change:(NSDictionary*)theChange context:(void*)theContext{ 

    if([keyPath isEqualToString:@"isFinished"]){ 

     NSLog(@"activity is finished with change: %@", theChange); 

     NSLog(@"target object: %@", self.selectorsParentObject); 
     NSLog(@"target selector: %@", NSStringFromSelector(self.selectorToCallWhenFinished)); 



     [self performSelectorOnMainThread:@selector(runCallback) withObject:nil waitUntilDone:NO]; 

     //[self performSelectorOnMainThread:self.selectorToCallWhenFinished withObject:self.resultData waitUntilDone:NO]; 
     //[self.selectorsParentObject performSelector:@selector(selectorToCallWhenFinished) withObject:self.resultData afterDelay:0]; 
    } 
} 

에서 해고와 -runCallback의 :

-(void)runCallback{ 

    [self.selectorsParentObject performSelector:self.selectorToCallWhenFinished withObject:self.resultData afterDelay:0]; 

} 

이 올바른 데이터 TheTask theSelector을했다. 참여해 주셔서 감사합니다 :