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.
}
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 the return
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
.
__block id result = nil;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSURLRequest *req = [self requestWithMethod:@"GET"
path:@"someURL"
parameters:nil];
AFHTTPRequestOperation *reqOp = [self HTTPRequestOperationWithRequest:req
success:^(AFHTTPRequestOperation *operation, id responseObject) {
result = responseObject;
dispatch_semaphore_signal(semaphore);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
dispatch_semaphore_signal(semaphore);
}];
reqOp.failureCallbackQueue = queue;
reqOp.successCallbackQueue = queue;
[self enqueueHTTPRequestOperation:reqOp];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(semaphore);
return result;
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.
- (void)methodUsingJsonFromSuccessBlock:(id)json {
// use the json
NSLog(@"json from the block : %@", json);
}
- (void)someFunction {
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id json){
// use the json not as return data, but pass it along to another method as an argument
[self methodUsingJsonFromSuccessBlock:json];
}
failure:nil];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation: operation];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With