0

我想運行一個併發的NSOperation。出於這個原因,我擴展了NSOperation類並重寫了開始和結束方法。它看起來是這樣的:完成併發NSOperation塊不被每次調用

#import "AVFrameConversionOP.h" 


@implementation AVFrameConversionOP //extends NSOperation 

- (void)start 
{ 

    [self willChangeValueForKey:@"isFinished"]; 
    _isFinished = NO; 
    [self didChangeValueForKey:@"isFinished"]; 

    // Begin 
    [self willChangeValueForKey:@"isExecuting"]; 
    _isExecuting = YES; 
    [self didChangeValueForKey:@"isExecuting"]; 

    if (_isCancelled == YES) { 
     NSLog(@"** OPERATION CANCELED **"); 
     [self willChangeValueForKey:@"isFinished"]; 
     _isFinished = YES; 
     [self didChangeValueForKey:@"isFinished"]; 
     return; 
    } 

    [self performTask]; 
    [self finish]; 

} 

- (void)finish 
{ 

    [self willChangeValueForKey:@"isExecuting"]; 
    [self willChangeValueForKey:@"isFinished"]; 

    _isExecuting = NO; 
    _isFinished = YES; 

    [self didChangeValueForKey:@"isExecuting"]; 
    [self didChangeValueForKey:@"isFinished"]; 

    NSLog(@"operationfinished, _isFinished is %d", _isFinished); 

    if (_isCancelled == YES) 
    { 
     NSLog(@"** OPERATION CANCELED **"); 
    } 
} 

- (void)performTask 
{ 
    //The task is performed here 
    sleep(0.1); //This is just for demonstration purposes 
} 
@end 

我在viewDidLoad方法定義的塊完成此的NSOperation主視圖控制器:

- (void)viewDidLoad { 

NSLog(@"viewDidLoad!"); 
[super viewDidLoad]; 

static int counter = 0; 


_frameConvOP = [[AVFrameConversionOP alloc] init]; //Initializing the modified NSOperation class 
__weak typeof(self) weakSelf = self; 
_frameConvOP.completionBlock =^{ 
    counter++; 
    //NSLogs don't seem to work here 
    /*if(counter>1){ 
     exit(-1); //Never happens because counter only ever becomes =1 
    }*/ 

}; 
[[VideoPreviewer instance] setNSOperation:_frameConvOP]; //This is where I send the NSOperation object to the class where I'm using it 

} 

我開始的NSOperation做[frameConvOP start]內一個循環。每次幀被解碼時都會被連續調用,這就是說它經常被調用。我可以看到,NSOperation的finishstart方法正在通過日誌頻繁調用。而且這些方法中的函數也被正確調用。但是,阻塞完成內部的NSLogs不會被記錄。我在完成塊中放置了一個退出(-1),並且應用程序崩潰了,但NSLogs從不出現。所以我把一個靜態計數器放在那裏,它只增加到1.所以完成塊只被調用一次。

任何人都可以解釋爲什麼完成塊只被調用一次?是否因爲我(錯誤地)處理_isFinished_isExecuting的KVO?當_isFinished設置爲YES時,應該調用完成塊,並且據我所知,我正在完成塊中執行該操作。結束塊被調用的頻率很高,因爲它應該是。

任何幫助,指導或方向表示讚賞。請讓我知道,如果我有任何錯誤,或者如果我在這篇文章中不太清楚。

感謝,

回答

0

NSOperation class reference

的操作對象爲單次對象,也就是說,它一旦執行其任務,不能用於再次執行。

您不允許在單個操作對象上多次調用-start

另一件事,在您的-finish方法中,您需要正確嵌套調用-willChange...-didChange...。也就是說,你需要調用-didChange...-willChange...調用的相反順序:

[self willChangeValueForKey:@"isExecuting"]; 
[self willChangeValueForKey:@"isFinished"]; 

_isExecuting = NO; 
_isFinished = YES; 

[self didChangeValueForKey:@"isFinished"]; 
[self didChangeValueForKey:@"isExecuting"]; 
+0

感謝您的答覆。我按照你的建議對嵌套進行了修改。那開始和結束方法是如何被成功調用多次的,並且它只是被調用一次的完成塊?而不是設置自己的開始和結束方法的目的,以便您可以重複調用任務? – C4DZ

+0

我不知道它是如何更清晰的:「NSOperation」的實現是圍繞它只能運行一次的規則構建的。完成塊只會被調用一次並不令人驚訝。 (文檔實際上說,對於當前版本的iOS,一旦調用它就會被清除。)實現自己的'-start'方法的目的是定製操作的功能。它與反覆運行無關,因爲這是違法的。實現'-finish'是無關緊要的,因爲'NSOperation'本身並不使用這種方法。這是你的班級特有的。 –

相關問題