Serialize calls to responseJSON using a lock.
AFJSONRequestOperation's completion path calls `responseJSON` from a processing queue. Because `responseJSON` "lazily" deserializes the response data into a JSON object, it needs to be protected against concurrent access from other queues (threads). For example, `AFNetworkingOperationDidFinishNotification` is posted when the operation finishes but perhaps before that processing queue has finishing executing. Notification observers who also access `responseJSON` end up in a race with that queue that often leads to a crash. We reuse the existing lock from our AFURLConnectionOperation base class.
This commit is contained in:
parent
eac6ffbb6e
commit
0dbff8387b
1 changed files with 6 additions and 0 deletions
|
|
@ -31,6 +31,10 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
|||
return af_json_request_operation_processing_queue;
|
||||
}
|
||||
|
||||
@interface AFURLConnectionOperation ()
|
||||
@property (readwrite, nonatomic, strong) NSRecursiveLock *lock;
|
||||
@end
|
||||
|
||||
@interface AFJSONRequestOperation ()
|
||||
@property (readwrite, nonatomic, strong) id responseJSON;
|
||||
@property (readwrite, nonatomic, strong) NSError *JSONError;
|
||||
|
|
@ -61,6 +65,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
|||
|
||||
|
||||
- (id)responseJSON {
|
||||
[self.lock lock];
|
||||
if (!_responseJSON && [self.responseData length] > 0 && [self isFinished] && !self.JSONError) {
|
||||
NSError *error = nil;
|
||||
|
||||
|
|
@ -77,6 +82,7 @@ static dispatch_queue_t json_request_operation_processing_queue() {
|
|||
|
||||
self.JSONError = error;
|
||||
}
|
||||
[self.lock unlock];
|
||||
|
||||
return _responseJSON;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue