Reputation: 1615
At first
I have this
ZTCAPIClient *api = [ZTCAPIClient sharedClient];
__block BOOL sessionSuccess = NO;
//Get session
[api getPath:@"api-getsessionid.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
NSMutableDictionary *dict = [self dealWithZTStrangeJSON:JSON];
if ([dict count]) {
NSLog(..something..);
sessionSuccess = YES;
NSLog(@"inside:%u",sessionSuccess);
} else {
NSLog(@"ERROR: Get no session!");
sessionSuccess = NO;
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"ERROR: %@",error);
sessionSuccess = NO;
}];
[api.operationQueue waitUntilAllOperationsAreFinished];
NSLog(@"outside:%u",sessionSuccess);
but I will get:
outside:0
inside:1
I know it's the async reason. So I searched on the Internet, then I found this: wait until multiple operations executed - including completion block (AFNetworking)
So I try it:
ZTCAPIClient *api = [ZTCAPIClient sharedClient];
__block BOOL sessionSuccess = NO;
dispatch_group_t group = dispatch_group_create();
//Get session
dispatch_group_enter(group);
[api getPath:@"api-getsessionid.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
NSMutableDictionary *dict = [self dealWithZTStrangeJSON:JSON];
if ([dict count]) {
NSLog(..something..);
sessionSuccess = YES;
NSLog(@"inside:%u",sessionSuccess);
} else {
NSLog(@"ERROR: Get no session!");
sessionSuccess = NO;
}
dispatch_group_leave(group);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"ERROR: %@",error);
sessionSuccess = NO;
dispatch_group_leave(group);
}];
//[api.operationQueue waitUntilAllOperationsAreFinished];
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
DLog(@"outside:%u",sessionSuccess);
then I get nothing... nothing output.
Where is wrong?
Upvotes: 0
Views: 1491
Reputation: 4162
You're probably not getting any output because your program is never moving past the call to dispatch_group_wait
. If it did, then you'd see the "outside" log statement.
If dispatch_group_wait
is never returning, then there must still be something in the group. In your sample code, you add one thing to the group with dispatch_group_enter
and then remove it in either the success or failure handler for the api call with dispatch_group_leave
. This means that dispatch_group_leave
is not being called for some reason.
My suspicion is that the reason the blocks are not being called is that they will be invoked asynchronously on the same dispatch queue that your outer code runs on. If this is the case, then they can't run until dispatch_group_wait
returns and dispatch_group_wait
cannot return until the blocks run. This is called deadlock. (Edit: Alternatively, it could be that some part of the program that invokes the success or failure blocks is the part that is leading to deadlock. Either way, the result is that the blocks can't get called since dispatch_group_wait
never returns.)
The other possibility is that the method -dealWithZTStrangeJSON:
never returns for some reason. If this is the case, then the success block will be invoked (you could set a breakpoint on its first line to verify), but it will never make it to dispatch_group_leave
.
In either case, I would recommend that you think about solving your problem another way instead of waiting for the operation to finish. Perhaps you can do the things that you were planning to do after dispatch_group_wait
returns inside of the success handler instead (or another way of thinking about it would be that the success or failure handler could call a method that does the things you're currently doing after dispatch_group_wait
—either way will work, but sometimes I find that it's easier to keep my code organized by calling out to a method instead of putting all of the code in a block. This could be especially useful if you want to share some code between the success and failure blocks).
Upvotes: 3