开发者

Perform selector on parent NSOperation

开发者 https://www.devze.com 2022-12-30 03:39 出处:网络
I extend NSOperation (call it A) which contains NSOperationQueue for other NSOperations (which is another extended class different from A, call these operations B). When operation A is running (execut

I extend NSOperation (call it A) which contains NSOperationQueue for other NSOperations (which is another extended class different from A, call these operations B). When operation A is running (executing B operations) how do i call a specific function/method on operation A when certain event takes place on B operations? For example every operation B that finishes it calls a function on operation A returning itself?

*Nested NSOperation and NSOperationQueue(s)

Hope this mockup pseudo code can help to draw the picture.

//My classes extended from NSOperation

NSOperation ClassA

NSOperation ClassB

//MainApp

-(void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    ClassA A1;

    ClassA A2;

    NSOperationQueue Queue;
开发者_开发问答    Queue AddOperation: A1;
    Queue AddOperation: A2;


}

//Main of ClassA

-(void)main {

     ClassB B1;

     ClassB B2;

     NSOperationQueue Queue;
     Queue AddOperation: B1;
     Queue AddOperation: B2;

}

//Main of ClassB

-(void)main {

   //Do some work and when done call selector on ClassA above

}


NSOperation has a mechanism to register dependencies. See NSOperation's documentation and addDependency:.

Let's split the work your A does: AX: spawning Bs, and AY: collecting the data in B. I think it's better to design B so that it can be used without A. Let B just download the data and hold it in the property data, as in

@interface B:NSOperation{
}
-initWithURL:(NSURL*)url atPosition:(NSUInteger)position;
@property (readonly)NSData* data;
@end;

A doesn't have to have its own queue, one per object. Generating B's doesn't take much time either, so AX doesn't have to be an operation.

So, I would just define the operations AY and B, prepare just one queue, and perform something like

NSOperationQueue* queue=...;
NSArray* urls = ... ;
for(NSURL* url in urls){
     AY* ay=[[AY alloc] init];
     for(chunks in url){
         B* b= an instance for B for the chunk in url
         [ay addDependency:b];
         [queue addOperation:b];
     } 
     [queue addOperation:ay];
}

Then, in AY's main, you can

-main{
      NSArray*bs=[self dependencies];
      for(B*b in bs){
           NSData* data=b.data;
      }
}

Note that, thanks to the dependencies, it's guaranteed that when AY is run, all of the B's has finished its operation. This way, the implementation of B is independent of A.


I've written a class called MXSuperOperation to nest NSOperations for the app I'm currently working on. I've posted it here:

https://gist.github.com/joerick/e4d2c99a2127715d9bc3

Subclass MXSuperOperation and add suboperations in the -mainError: method.

@interface OperationA : MXSuperOperation

@end

@implementation OperationA

- (BOOL)mainError:(NSError **)error
{
    [self addSuboperation:[OperationB new]];
    [self addSuboperation:[OperationB new]];

    return YES;
}

@end

Then to run something at the end of all the OperationBs, you can either add a completionBlock to operationA:

[operationA setCompletionBlockWithSuccess:^(id operation) {
    NSLog(@"success");
} failure:^(id operation, NSError *error) {
    NSLog(@"error %@", error);
}];

Or you can implement -endError: in OperationA (depending on how you want to structure the code).

Note that this class is built on an NSOperation subclass I made called MXCheckedOperation, which just codifies success/failure and error reporting for NSOperations.

0

精彩评论

暂无评论...
验证码 换一张
取 消