2011-01-20 5 views
3

Для приложения iOS4.X, над которым я работаю, нам часто нужно выполнить HTTP-запрос, затем проанализировать результаты и сделать что-то с результатами и так далее.Композитный NSOperation. Это плохая идея?

Для этого я создал класс NSOperation, позволяющий создавать NSOperations с использованием очереди NSOperation. Есть ли проблема с использованием NSOperationQueues для небольших вещей, подобных этому. Некоторые сказали мне, что очереди должны быть более постоянными.

Я не ожидаю, что гнездование будет более чем на 2 уровня в нашем приложении.

Вот пример такого использования:

@implementation CompositeOperation 

- (id)initWithOperations:(NSArray *)operations { 
    if ((self = [super init])) { 
     operations_ = [operations retain]; 
     [[operations_ lastObject] addObserver:self forKeyPath:@"isFinished" options:NSKeyValueObservingOptionNew context:nil]; 

    } 
    return self; 
} 

-(void)dealloc { 
    [operations_ release]; 
    [operationQueue_ release]; 
    [super dealloc]; 
} 

- (BOOL)isConcurrent { 
    return YES; 
} 

@synthesize isExecuting = isExecuting_; 
@synthesize isFinished = isFinished_; 
@synthesize operations = operations_; 

- (void) start { 
    if (![self isCancelled]) { 
     operationQueue_ = [[NSOperationQueue alloc] init]; 
     // TODO: Add code to execute this serially 
     [operationQueue_ addOperations:operations_ waitUntilFinished:NO]; 
    } 
} 

- (void)cancel { 
    if (operationQueue_) { 
     [operationQueue_ cancelAllOperations]; 
    } 
    [super cancel]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if ([keyPath isEqualToString:@"isFinished"] && object == [operations_ lastObject]) { 
     [self setIsFinished:YES]; 
    } 
} 

@end 

Спасибо, Майк

+1

Нет необходимости создавать отдельный класс для этого, просто используйте NSOperationQueue. Если вам нужно дождаться завершения всех операций, дождитесь самой очереди или проверите ее периодически или просто выполните последнюю операцию, но отправьте уведомление о том, что очередь выполнена. Чтобы сделать очередь очередью, просто отправьте [queue setMaxConcurrentOperationCount: 1]; –

+2

Jason: Цель этого объекта - сделать так, чтобы можно было представлять несколько операций, которые логически сгруппированы как одна операция. – mikelikespie

ответ

2

Я тот, кто думает, что это очень хорошая идея, так что я даже создал библиотеку после этого: CompositeOperations.

Существует две операции: простая операция, представленная COSimpleOperation объектом и композитной операцией, представленной COCompositeOperation объектом.

Простая операция является минимально возможный блок - процитировать документации:

В двух словах COSimpleOperation является NSOperation с небольшим небольшим количеством сахара удобства поверх него. В качестве операционного блока для составных операций он обычно соответствует одному сетевому запросу или небольшому сосредоточенному фрагменту работы.

Композитная операция - операция, состоящая из подопераций. Для цитирования @mikelikespie:

Цель этого объекта - сделать так, чтобы можно было представлять несколько операций, которые логически сгруппированы как одна операция.

... который является довольно большим описанием другого композитного рисунка дизайна из шаблона дизайна банды четырех.

Композитная операция может быть parallel или sequential.

Параллельные операции создаются так же, как в примере кода в вопросе:

NSArray *operations = @[ 
    operation1, operation2, operation3 
]; // each operation is NSOperation <COOperation> * 

COCompositeOperation *parallelOperation = [[COCompositeOperation alloc] initWithOperations:operations]; 

Чтобы создать последовательную операцию нужно создать экземпляр COCompositeOperation с объектом в соответствии с COSequence протокола:

Последовательная композиция предполагает последовательное поток: под-операции выполняются поочередно один за другим. Секвенирование достигается посредством сотрудничества между COCompositeOperation и произвольным классом, соответствующим протоколу COSequence, который используется составной операцией в качестве делегата, который решает, какие операции и в каком порядке их запускать.

Для того, чтобы этот состав операций возможно мне нужно было поставить небольшое ограничение на операции библиотеки работы с: помимо того, что NSOperations как COSimpleOperation и COCompositeOperation также соответствуют <COOperation> протокола:

Это соответствие в основном означает, что обе операции, когда закончили есть 3 возможных состояния:

  1. непустое поле результата показывает успех

  2. непустое поле ошибка указывает на неисправность

  3. оба результата пустые поля и ошибок указывают, что операция была отменена из-за пределов (с помощью - [NSOperation отменить] метод).

Операция никогда не может иметь как поля результата, так и ошибки не пустые!

Это соглашение позволяет композитным операциям в определенный момент решать, продолжать ли выполнение определенной группы операций или остановить ее. Для операций без определенного результата [NSNull null] следует передать в качестве результата.


Для меня рациональный позади этой библиотеки был «просто», чтобы иметь возможность представлять операции таким образом «что они логически сгруппированы в одной операции». Существуют библиотеки, которые достигают такого же уровня функциональности более высокого уровня, но в то же время внедряют такие понятия, как: Сигналы в ReactiveCocoa или Обещания, как в PromiseKit, которые мне действительно не нужны, или я бы сказал, не согласен с ними. Я хотел что-то как можно более простое и основанное на старой доброй известной инфраструктуре NSOperation/NSOperationQueue, так что это все усилия.

P.S. Я надеюсь, что такой ответ соответствует SO, по крайней мере, он точно соответствует тому, что @mikelikespie спрашивал около 4 лет назад.

+0

Мне было бы очень интересно узнать, обновите ли вы этот подход для быстрого, например, для использования генериков – algal

+0

@algal, это то, что я очень хотел сделать, но я не нашел подходящего времени. Я был бы рад узнать о любом прогрессе, который вы могли бы сделать здесь. Если вам нужна вторая пара глаз/рук, я мог бы участвовать. Свифт действительно очень перспективен в этом направлении, особенно его перечисления и дженерики. –

Смежные вопросы