In late 2011 I found the need to use the same concurrent NSOperation feature, but in a class not descended from UIViewController. I had two choices: either duplicate the NSOperations code in a second subclass, or find a way to extract it into something I could re-use anywhere.

I choose the second approach, and created OperationRunner, a helper class that I use to this day. In the end, this helper class can be incorporated into any Objective-C class by taking 6 or so simple steps as outlined in the OperationsRunner.h file. This involves adding imports for this header file and another header with a single protocol callback method. The actual operations are subclasses of a single NSOperation subclass, ConcurrentOperation. A further subclass, WebFetcher, adds web functionality. [In my current code I have a half dozen or so such subclasses.] I created this code on my own time, and thus can incorporate it elsewhere as I see fit as I own it.

The helper class provides a small set of methods:

  • (id)initWithDelegate:(id <OperationsRunnerProtocol>)del;
  • (void)runOperation:(NSOperation *)op withMsg:(NSString *)msg;
  • (NSSet *)operationsSet;
  • (NSUInteger)operationsCount;
  • (void)cancelOperations;
  • (void)enumerateOperations:(void(^)(NSOperation *op)) b;

Operations are submitted with the runOperation and an optional debug message, which can get logged when the operations gets submitted to the NSOperationsQueue, and also when it completes. This is quite handy during debugging, and in my code I always supply a string, but suppress logging if the build is Deployment.

The completed operation is returned to the caller object via a delegate message:

– (void)operationFinished:(NSOperation *)op;

Within that message, the OperationsRunner object can report back whether this is the last operations, or others are still pending (they might even be all complete but have not been fed back via the delegate message.)

Queued operations can be cancelled at any time, and the whole stack quickly and gracefully collapses—cancelled operations do not result in delegate callbacks either.

My code has made extensive use of this class, and actually uses the exact code found in the NSOperation-WebFetches-MadeEasy repository. My last App Store App, Lot18, made extensive use of it, and often had hundreds of html and image fetches going on in multiple instances of the OperationsRunner. Refinements made at this time included the ability to vary the maximum number of concurrent operations, and the priority of the serial dispatch queue used to manage the operations. This architecture let the UI be responsive even in the face of a huge amount of background work (and the app has a 5 star rating!)

I am aware of many other networking frameworks, but mine does not try to be all inclusive—it does one thing really well—and it does what it aims to do quite well (YMMV). It’s something I’m very proud of, and I hope others will find it useful.