AFNetworking/AFNetworking — pull request #316 by dismory (2012-04-25 08:04:38+00:00)
Title: Fix the duplicated `AFJSONDecode()` calling that cause message sending t...

...o deallocated `NSError` object

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.

Details see comments in code blew.

**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) {
/**
`responseJSON` second call, PART II
*/
failure(operation.request, operation.response, error, [(AFJSONRequestOperation *)operation responseJSON]);
}
}];

return requestOperation;
}
```

```
- (id)responseJSON {
/**
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
*/
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished]) {
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(), ^{
/**
`responseJSON` first call
*/
id JSON = self.responseJSON;

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