AFNetworking/AFNetworking — pull request #315 by dismory (2012-04-25 07:49:53+00:00)
Title: Fix send msg to deallocated error

After a long time debug, I found the reason for the problem my previous pull request that want to fix is that `AFJSONDecode()` was called twice for single `AFJSONRequestOperation` when failing to parse the JSON data. If JSON is parsed successfully, this will not happen.

**AFJSONRequestOperation.m**
```
+ (AFJSONRequestOperation *)JSONRequestOperationWithRequest:(NSURLRequest *)urlRequest
success:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, id JSON))success
failure:(void (^)(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON))failure
{
AFJSONRequestOperation *requestOperation = [[[self alloc] initWithRequest:urlRequest] autorelease];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
success(operation.request, operation.response, responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (failure) {
failure(operation.request, operation.response, error, [(AFJSONRequestOperation *)operation responseJSON]); // `responseJSON` second call, PART II
}
}];

return requestOperation;
}

- (id)responseJSON {
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished]) { // if fail to parse JSON, this condition wil allow to call twice, and previous generated `error` is deallocated, however the deallocated one is already sent to the failure block
NSError *error = nil;

if ([self.responseData length] == 0) {
self.responseJSON = nil;
} else {
self.responseJSON = AFJSONDecode(self.responseData, &error);
}

self.JSONError = error;
}

return _responseJSON;
}

- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
self.completionBlock = ^ {
if ([self isCancelled]) {
return;
}

if (self.error) {
if (failure) {
dispatch_async(self.failureCallbackQueue ? self.failureCallbackQueue : dispatch_get_main_queue(), ^{
failure(self, self.error);
});
}
} else {
dispatch_async(json_request_operation_processing_queue(), ^{
id JSON = self.responseJSON; // `responseJSON` first call

if (self.JSONError) {
if (failure) {
dispatch_async(self.failureCallbackQueue ? self.failureCallbackQueue : dispatch_get_main_queue(), ^{
failure(self, self.error); // `responseJSON` second call, PART I
});
}
} else {
if (success) {
dispatch_async(self.successCallbackQueue ? self.successCallbackQueue : dispatch_get_main_queue(), ^{
success(self, JSON);
});
}
}
});
}
};
}

```