2

我無法在網絡上的其他任何地方找到答案,所以任何幫助將不勝感激。NSOperation子類performSelector

我綁定創建一個系統,我可以檢索NSOperation任務的結果,我明白不能由具體的子類,如NSInvocation完成。

我有一個子類的NSOperation(TheEngine),它是按照慣例抽象和必須擴展到實現該功能-main,以包括代碼以執行該主體。

TheEngine包含以下功能初始化他們的工作很簡單,就是注意theSelectortheObject選擇所屬。它還會註冊一個KV觀察員財產isFinished

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

在我observeValueForKeyPath:ofObject:change:context:功能,我想調用回調函數,像這樣:

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

整個過程是這樣的:

aViewController啓動延伸TheEngine - 可以說TheTask通過調用以下內容並將其添加到操作隊列中。

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:不需要運行循環。

+0

感謝您的提示,你的預感變成了正確的 - 我會發布我所做的更改:) – aktar

0

作爲羅布建議,代碼在後臺線程運行,因爲是召喚observeValueForKeyPath:ofObject:change:context:

我最初改變了代碼,這樣選擇是在主線程中發射與[self performSelectorOnMainThread:@selector(runCallback) withObject:nil waitUntilDone:NO];

但是,在這種情況下,主線程原來是TheTask和一個異常被拋出TheTask沒有自己theSelector。爲了解決這個問題,我創建了一個額外的功能-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]; 

} 

稱爲theSelector TheTask用正確的數據。 感謝您的參與:)