Reputation: 13
I have a method which helps me sync my local standardUserDefaults with a Web Service. First, I need to make sure that data has been synced successfully, then I can let the method return. The problem I am currently striving to resolve is that I can't get the GCD to execute & finish the tasks in a certain order: firstly POSTing to the web service and secondly returning.
The problem is that the second dispatch_sync task finishes execution first, then comes the first dispatch_sync task. How to I make sure the execution happens as scheduled? Is this a special case because of the NSURLSessionDataTask?
Thanks a lot!
-(void) syncLocalStorageToMMUsersDB:(void(^)(bool success))handler
{
__block bool fb_sync_success = 0;
dispatch_queue_t requestQueue = dispatch_queue_create("com.micromorts.request", DISPATCH_QUEUE_SERIAL);
//if logged in with Facebook, then sync it
if ([_defaults stringForKey:MMFBIdPrefsKey]) {
// Start NSURLSession
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];
// POST parameters
NSURL *url = [NSURL URLWithString:@"http://THE.URL.GOES.HERE"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
NSString *params = [POST PARAMS GO HERE];
[urlRequest setHTTPMethod:@"POST"];
[urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
// NSURLSessionDataTask returns data, response, and error
NSURLSessionDataTask *dataTask =[defaultSession dataTaskWithRequest:urlRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// Handle response
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger statusCode = [httpResponse statusCode];
if(error == nil) {
if (statusCode == 404) {
NSLog(@"MMAuth.m :: syncLocalStorageToMMUsersDB FB :: FB User not found");
fb_sync_success = false;
} else if (statusCode == 200) {
NSLog(@"MMAuth.m :: syncLocalStorageToMMUsersDB FB :: Successfully synced ");
fb_sync_success = true;
} else {
NSLog(@"MMAuth.m :: syncLocalStorageToMMUsersDB FB :: Sync fail ");
fb_sync_success = false;
}
}
}
];
//This should finish EXECUTING first
dispatch_sync(requestQueue, ^{
[dataTask resume];
});
}
//This should finish EXECUTING second
dispatch_sync(requestQueue, ^{
if (fb_sync_success){
NSLog(@"SUCCESS");
} else {
NSLog(@"FAILED");
}
});
}
Upvotes: 1
Views: 296
Reputation: 162722
If the call to [dataTask resume];
is asynchronous, then that dispatch_sync()
will return immediately after -resume
executes and then the subsequent dispatch_sync()
will be enqueued and executed immediately after (but before the data is loaded).
Move your SUCCESS/FAILED logic into the completion handler block; that is why completion handlers exist.
Upvotes: 3