Ganesh G
Ganesh G

Reputation: 2061

"addDependency" is not working properly in iOS

I have two NSOperation objects "A" and "B", and want to use dependency as I need to let complete "B" first and then start "A".

- (void)viewDidLoad {
    [super viewDidLoad];

    NSOperationQueue *myQueue = [NSOperationQueue new];
    NSOperation *op1 = [[NSOperation alloc] init]; // Its a background(concurrent) thread.
    op1.completionBlock =^{
        NSLog(@"A");  
    };

    NSOperation *op2 = [[NSOperation alloc] init];  
    op2.completionBlock =^{

        NSLog(@"B");
    };
    [op1 addDependency:op2];
    [myQueue addOperation:op1];
    [myQueue addOperation:op2];
}

Expected Output:

 B
 A

But sometimes:

 A
 B

But I want to complete first B and then need to start A. Please help me on it.

Upvotes: 1

Views: 696

Answers (3)

Sangram Shivankar
Sangram Shivankar

Reputation: 3573

  1. First Create Operation op1
  2. If data provided by Operation op2 is not available, create Operation op2
  3. make Operation op1 dependent on Operation op2. ie. something like op1.addDependency(op2);

or check this also

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSOperation *op1;
NSOperation *op2;

//... initialize op1 and op2 however you please ...

[op1 setCompletionBlock:^{
        if ([op1 satisfiesSomeCriteria]) {
            [queue addOperation:op2];
        }
 }];
[queue addOperation:op1];

Upvotes: 1

Ganesh G
Ganesh G

Reputation: 2061

I could able to achieve it by using NSBlockOperationclass instead of NSOperation. Here is a sample code snippet.

    NSOperationQueue *myQueue = [NSOperationQueue new];
    NSBlockOperation *blockOp1 = [[NSBlockOperation alloc] init];
    [blockOp1 addExecutionBlock:^{

        NSLog(@"1");
    }];

    NSBlockOperation *blockOp2 = [[NSBlockOperation alloc] init];
    [blockOp2 addExecutionBlock:^{

    NSLog(@"2");
    }];

    [blockOp1 addDependency:blockOp2];
    [myQueue addOperation:blockOp1];
    [myQueue addOperation:blockOp2];

   Output: 2
           1

Upvotes: 0

vaibhav
vaibhav

Reputation: 4096

Here completion blocks are not part of the queue instead they run outside of the Operation Queue on another thread. Thus Operation A's completionBlock will run at the same time as Operation B.

According to your ques you are using the completionBlocks to pass information from operation A to B.

Here are some solution:

  • Give B references to all the A's (not weak) so when B runs it can pick the results from operation A.

  • keep all the A operation around until B runs, then recreate your Completion Block's as another NSOperation see code below:


NSOperation *operA = [NSBlockOperation blockOperationWithBlock:^{ // do stuff 
}]; 

NSOperation *operationATail = [NSBlockOperation blockOperationWithBlock:^{ // do completionBlock stuff
}]; 

// First bullet point
[operationATail addDependency:operA];

// Second bullet point
[operationB addDependency:operationATail]; 

[self.queue addOperations:@[operA, operationATail, operationB] waitUntilFinished:NO];

Upvotes: 1

Related Questions