I’ve been a bit detached from Cocoa and Objective-C for the last year or so with lower level cross platform libraries like boost and mainly boost::asio. Concurrency has always been an issue with me as I despise threads and ever moreso hate locks. Granted they are needed under certain conditions or programming models.
The NSOperation and NSOperationQueue classes are a godsend and have been needed for a very long time. I’ve always said that if you can asynchronously create an object and pass it off to the kernel to perform it’s process and return on a user defined callback that it’s the best option.
My reasoning for feeling this way about threads is that under no condition does an application know how many threads it should be using at any given time and therefore is an issue in it’s own right.
Below I give an example of an NSOperation subclass that downloads arbitrary data from an NSURL and then calls it’s delgate when the operation has completed in the NSOperationQueue.
The Interface:
@interface JCNetworkDataOperation : NSOperation
{
id _delegate;
NSURL * _url;
}
@property (nonatomic, assign) id __weak delegate;
@property (nonatomic, retain) NSURL * url;
@end
The implementation:
@implementation JCNetworkDataOperation
@synthesize delegate = _delegate;
@synthesize url = _url;
- (void)main
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSError * err = nil;
NSData * data = [[NSData alloc]
initWithContentsOfURL:self.url options:NSUncachedRead error:&err
];
if (err)
{
JCLog([err localizedDescription]);
}
else
{
if ([self.delegate
respondsToSelector:@selector(networkDataOperationDidComplete:)]
)
{
[self.delegate
performSelectorOnMainThread:@selector(
networkDataOperationDidComplete:) withObject:data
waitUntilDone:NO
];
}
}
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)dealloc
{
[_url release];
[super dealloc];
}
@end
Use case:
JCNetworkDataOperation * networkDataOperation = [[
JCNetworkDataOperation alloc] init
];
networkDataOperation.delegate = self;
networkDataOperation.url = url;
[appDelegate.operationQueue addOperation:networkDataOperation];
[networkDataOperation release];
And the delegate method:
- (void)networkDataOperationDidComplete:(NSData *)aData
{
if (aData.length)
{
}
}
This is a very simple example of using NSOperation with NSOperationQueue, however it’s only limits are in your imagination.