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 

Я определил блок завершения для этого NSOperation в главном контроллере представления в методе viewDidLoad:

- (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] внутри петля. Он вызывается непрерывно каждый раз, когда кадр декодируется, так что это называется очень часто. Я вижу, что методы 0Sи start NSOperation часто вызываются через журналы. И функции внутри этих методов также правильно называются. Однако NSLogs внутри блокированного завершения не регистрируются. Я положил выход (-1) внутри блока завершения, и приложение разбилось, но NSLogs никогда не появлялись. Поэтому я помещаю статический счетчик там, и он только увеличивается до 1. Таким образом, блок завершения вызывается только один раз.

Может кто-нибудь объяснить, почему блок завершения вызывается только один раз? Это из-за того, как я (неправильно) обрабатываю KVO для _isFinished и _isExecuting? Блок завершения должен вызываться, когда _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' сам не использует этот метод. Это характерно для вашего класса. –