0

I have Table View Controller with collection of cells, each cell displays 2 values:

–––––––––––––––––––––––––
| cell1                 | val1 | val2 |
–––––––––––––––––––––––––
| cell2                 | val1 | val2 |
–––––––––––––––––––––––––

I need to perform a serial synchronous operation with these cells with algorithm like this:

  1. setup core data & update tableView UI
  2. iterate cells
    2.1 update tableViewCell UI
    2.2 iterate values
        2.2.1 update value UI
        2.2.2 download new value
            2.2.2.1 if failed repeat iteration
        2.2.3 save & update value UI
    2.3 update tableViewCell UI
  3. save & update tableView UI

I’m using NSOperationQueue with NSBlockOperations:

- (void)startOperation:(id)sender {



    operationQueue = [NSOperationQueue new];
    operationQueue.name = @"Operation Queue";
    operationQueue.maxConcurrentOperationCount = 1;
    [operationQueue waitUntilAllOperationsAreFinished];



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

        NSLog(@"Prepare Core Data");
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"Update tableView UI");
        }];

    }];
    [operationQueue addOperation:prepareCoreData];





    NSBlockOperation * iterateCells = [[NSBlockOperation alloc] init];
    __weak NSBlockOperation * weakIterateCells = iterateCells;
    [iterateCells addExecutionBlock:^{


        for (Item * item in self.items.fetchedObjects) {



                    if ([weakIterateCells isCancelled]) break;

                    NSBlockOperation * setCellUI = [[NSBlockOperation alloc] init];
                    [setCellUI addExecutionBlock:^{
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            NSLog(@"        Set tableViewCell UI");
                        }];

                    }];
                    [operationQueue addOperation:setCellUI];





                    NSBlockOperation * iterateValues = [[NSBlockOperation alloc] init];
                    __weak NSBlockOperation * weakIterateValues = iterateValues;
                    [iterateValues addExecutionBlock:^{

                            for (SearchEngine * s in self.searchEngines) {

                                    if ([weakIterateValues isCancelled]) break;




                                    NSBlockOperation * setValueUI = [[NSBlockOperation alloc] init];
                                    [setValueUI addExecutionBlock:^{
                                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                            NSLog(@"        Set Value UI");
                                        }];

                                    }];
                                    [operationQueue addOperation:setValueUI];



                                    NSBlockOperation * getValue = [[NSBlockOperation alloc] init];
                                    [getValue addExecutionBlock:^{
                                        NSLog(@"        Download Value");
                                    }];
                                    [getValue addDependency:setCellUI];
                                    [operationQueue addOperation:getValue];



                                    NSBlockOperation * updateValue = [[NSBlockOperation alloc] init];
                                    [updateValue addExecutionBlock:^{
                                        NSLog(@"        Save Data");
                                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                                            NSLog(@"        Update Value UI");
                                        }];

                                    }];
                                    [updateValue addDependency:getValue];
                                    [operationQueue addOperation:updateValue];




                            }



                    }];
                    [iterateValues addDependency:setCellUI];
                    [operationQueue addOperation:iterateValues];



                    NSBlockOperation * updateCellUI = [[NSBlockOperation alloc] init];
                    [updateCellUI addExecutionBlock:^{
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            NSLog(@"        Update tableViewCell UI");
                        }];

                    }];
                    [updateCellUI addDependency:iterateValues];
                    [operationQueue addOperation:updateCellUI];

                };



    }];
    [iterateCells addDependency:prepareCoreData];
    [operationQueue addOperation:iterateCells];





    NSBlockOperation * completeOperation = [[NSBlockOperation alloc] init];
    [completeOperation addExecutionBlock:^{
        NSLog(@"Save Data");
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            NSLog(@"Update tableView UI");
        }];

    }];
    [completeOperation addDependency:iterateCells];
    [operationQueue addOperation:completeOperation];





}

With this code, last operation (#3) executes before all iterations are done.

I'm looking for suggestions on how to properly nest operations and queues to maintain serial order.

dsolimano
  • 8,870
  • 3
  • 48
  • 63
devster
  • 53
  • 1
  • 4
  • 1
    What's happening is that you're creating too many queues-- don't create the cell and value iteration queues-- put their work on the operationsQueue as well. All the work should take place on a single queue! – RibaldEddie Feb 09 '14 at 06:55
  • thanks for pointing that out, i updated the code but still getting same results, #3 operation happens before all iterations are done. – devster Feb 10 '14 at 05:22
  • Why are you adding new operations in the loops, and then adding the UI updates on the main thread inside the extra operation? Just do it right inside the loop. – RibaldEddie Feb 10 '14 at 16:45

0 Answers0