0
votes

I want to execute a few Networking methods using NSOperation for each one of them, and add the the operations to an NSOperationQueue that is set on a back thread, I want the NSOperations to happen serialized.

The call that creates the NSOperation queue is called periodically, each 30 seconds using an NSTimer.

Here is a code snipped so far:

NSTimer *timer;
NSOperationQueue *bgQueue;

- (void)startdDownloadLoop{

    if (![self.timer isValid]){

        self.bgQueue = [[NSOperationQueue alloc] init];
        self.timer = [NSTimer scheduledTimerWithTimeInterval:30.0
                                                      target:self
                                                    selector:@selector(updateDB)
                                                    userInfo:nil
                                                     repeats:YES];

    }

}

- (void)updateDB{

    //        Next code was removed since si similar to the call `[self.bgQueue cancelAllOperations];`, as @robinkunde suggested
    //        for (NSOperation *operation in [self.bgQueue operations]) {
    //            if (operation.isExecuting) {
    //                [operation cancel];
    //            }
    //        }

    [self.bgQueue cancelAllOperations];


    self.bgQueue = [[NSOperationQueue alloc] init];
    self.bgQueue.maxConcurrentOperationCount = 1;

    NSBlockOperation *blockOp1 = [NSBlockOperation blockOperationWithBlock:^{
        [NetworkManager downloadCars];
    }];

    NSBlockOperation *blockOp2 = [NSBlockOperation blockOperationWithBlock:^{
        [NetworkManager downloadPartsForAllCars];
    }];

    NSBlockOperation *blockOp3 = [NSBlockOperation blockOperationWithBlock:^{
        [NetworkManager downloadEachPathSpecs];
    }];

    [self.bgQueue addOperation:blockOp1];
    [self.bgQueue addOperation:blockOp2];
    [self.bgQueue addOperation:blockOp3];

}

The NetworkManager methods are POST/GET methods with completion handlers, that after they finish downloading, they save the date in DB and then update the UI using a notification.

Update:

Since the confusion, I thought to post my actual question regarding the code as fallows:

1- If the execution of the NSOperationQueue will be serial?

2 - if when I am calling the [operation cancel] will stop the execution of the operation?

3 - If when I am calling the cancelAllOperations and the I re-init it is the correct way of clearing the current NSOperationQueue?

1
It probably won't do what you want. Presumably each of the download... methods execute asynchronously. If so then as soon as the network operation is dispatched then the block will complete and the next submitted block will begin executing, even though the first download operation is not yet complete. You would probably be better off using a dispatch_group, or even better push notifications rather than polling which is expensive in terms of battery and network trafficPaulw11
As far as cancelling operations, it is up to each block to check the blocks isCancelled property and cease work if appropriately. The operation queue can't actually cancel an operation, it just sets the property to indicate to the operation that it should cancel itself. See stackoverflow.com/questions/8113268/…Paulw11

1 Answers

1
votes

1) You can set the property maxConcurrentOperationCount on the queue to 1 to ensure serial execution.

2) This only sets the isCancelled property on the operation. The needs to act on this change and move itself to the finished state so it can be removed from the queue.

As for your specific example: NSBlockOperation is considered finished when all attached blocks have returned. That actually means that unless the calls to NetworkManager are synchronous, the block returns immediately, the operation is considered finished, and the queue starts the next operation. It's entirely possible that the queue finishes before the first network operation completes. If you want to execute them one at a time, this is not the way to do it.

You could use synchronous network operations, but that still wouldn't allow you to cancel them.

Check out this answer: NSURLSession with NSBlockOperation and queues

3) This is related to 2). All cancelAllOperations does is set the isCancelled property on all operations. Until those operation are finished, the queue will continue to exist. Creating a new queue on the same property doesn't change that.