I have a function using AFJSONRequestOperation, and I wish to return the result only after success. Could you point me in the right direction? I'm still a bit clueless with blocks and AFNetworking specifically.
-(id)someFunction{
__block id data;
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json){
data = json;
return data; // won't work
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation: operation];
return data; // will return nil since the block doesn't "lock" the app.
}
It's worth noting that some features of AFNetworking's AFClient can still be used in a synchronous manner, meaning that you can still use niceties such as Authorisation headers and multipart uploads.
For example:
Remember to check
response.statusCode
in this case, as this method doesn't consider HTTP failure codes as errors.To expand/update @Kasik's answer. You can create a category on AFNetworking like so using semaphores:
If you are calling the sync block inside a completion block of another AFNetwork request, make sure you change the
completionQueue
property. If you don't change it, the synchronous block will call the main queue upon completion while already on the main queue and will crash your application.To block the execution of the main thread until the operation completes, you could do
[operation waitUntilFinished]
after it's added to the operation queue. In this case, you wouldn't need thereturn
in the block; setting the__block
variable would be enough.That said, I'd strongly discourage forcing asynchronous operations to synchronous methods. It's tricky to get your head around sometimes, but if there's any way you could structure this to be asynchronous, that would almost certainly be the way to go.
I'm using semaphores to solve this issue. This code is implemented in my own class inherited from
AFHTTPClient
.Add this below the code you normally work with:
Example:
I would suggest that you don't make a synchronous method with AFNetworking (or blocks in general). A good approach is that you make another method and use the json data from the success block as an argument.