A simple batching approach to dispatch_async in iOS

Dispatch_async and its cousins have been around for a while, and make a bunch of async operations a whole lot easier.

I have been looking for a nice easy way to perform operations in batches; dispatch_group_notify is nice, but you have no control over the batch size.

Here’s a simple way to batch updates to a mutable array of NSManagedObjects (useful when you want to do some action requiring network connectivity to each one).

Anyway – here it is:

 


-(void)performAction:(void(^)(NSManagedObject*item))action
           inContext:(NSManagedObjectContext*)temporaryContext
    withItemsInArray:(NSMutableArray*)arrayOfItems
    usingBatchSizeOf:(NSUInteger)batchSize
                then:(void(^)(void))finished;
{
    
    // if no items left, return
    if([arrayOfItems count] == 0){
        finished();
        return;
    }

    // take first items
    NSMutableArray *itemsToOperateOn;
    NSMutableArray *leftOvers;
    
    if([arrayOfItems count] < batchSize){
        itemsToOperateOn = [arrayOfItems copy];
        leftOvers = [NSMutableArray new];
    }else{
        itemsToOperateOn = [[arrayOfItems subarrayWithRange:NSMakeRange(0, batchSize)] mutableCopy];
        leftOvers = [[arrayOfItems subarrayWithRange:NSMakeRange(batchSize, [arrayOfItems count] - batchSize)] mutableCopy];
    }
    
    dispatch_group_t actionGroup = dispatch_group_create();
    for(NSManagedObject *itemToOperateOn in itemsToOperateOn)
    {
        dispatch_group_async(actionGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
            action(itemToOperateOn);
        });
    }

    // notify when done
    dispatch_group_notify(actionGroup, dispatch_get_main_queue(), ^{
        NSLog(@" - Batch Operation performed, %i left", [leftOvers count]);
        [temporaryContext save:nil];
        [self performAction:action inContext:temporaryContext withItemsInArray:leftOvers usingBatchSizeOf:batchSize then:finished];
    });
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s