Is This a Valid Way to Use Blocks in Objective-C?
- by Carter
I've been building a HTTP client that uses web services to synchronize information between the client and server. I've been using Blocks and NSURLConnection to achieve this on the client side, but I'm getting frequent EXC_BAD_ACCESS crashes in objc_msgSend(). From what I understand, this usually means that a stored block that has fallen off the stack has been called. I think I've coded things correctly to avoid this, but I'm still stuck.
Here is conceptually what my code is doing. It starts by calling "synchronizeWithWebServer". That method invokes "listRootObjectsOnServerWithBlock:" which takes in a block to be called when the method returns.
"listRootObjectsOnServersWithBlock:" initiates a NSURLConnection to the web server asynchronously. It to expects a block to be called when it returns. Inside that block I want to be able to execute the original Block (so aptly named 'block').
This is only a simplified version of my code. The real synchronization process is more complex but it's mostly more of the same as what you see below.
Sometimes the code works perfectly, but about 80% of the time it crashes very early on in the routine. It seems to be more vulnerable to crashing when my data set gets larger.
- (void)synchronizeWithWebServer
{
[self listRootObjectsOnServerWithBlock:^(NSArray *results, NSError *error) {
//Iterate over result objects and perform some other similar routines.
}];
}
- (void)listRootObjectsOnServerWithBlock:(void (^)(NSArray *results, NSError *error))block
{
//Create NSURLRequest Here
//Create connection asynchronously.
block = [block copy];
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue currentQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
//Parse response from web server (stored in NSData *data)
NSArray *results = .....
//Call 'block'
block(results, error);
[block release];
}];
}