Search code examples
iosjsonasynchronousafnetworking-3

Can't get response from async block using AFNetworking 3.0


I'm new to IOS development, so i'm probably just missing some basics. Have been struggling with this problem for 2 days already. So, here it is. I have a data task in my API class:

//request generation, putting url and dictionary into it

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];

NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
    if(!error)
    {
        self.jsonDictionary = responseObject;
        NSInteger HTTPStatusCode = [(NSHTTPURLResponse *)response statusCode];
        NSLog(@"RESPONSE DATA:  %@", self.jsonDictionary);
        self.didSendRequest = YES;
    }
    else
    {
        self.didSendRequest = NO;
        NSLog(@"ERROR:  %@", error);
    }
}];
[dataTask resume];

And then retrieve the json dictionary like this:

-(NSDictionary *)returnJSON{
if(self.didSendRequest) return self.jsonDictionary;
else NSLog(@"No dictionary dowloaded");
return self.jsonDictionary;}

Then, in other class i pass url and dictionary to the data task method, and get response just like this:

-(NSDictionary*)userLogin : (NSString* )email : (NSString*) password {
dataTaskClass* aph = [[dataTaskClass alloc] init];

NSDictionary *userParams = [[NSDictionary alloc] initWithObjectsAndKeys:
                            email,@"email",
                            password,@"password",
                            nil];
[aph postRequest: @"myUrl"];
return dataTaskClass.returnJSON;}

And then finally i call it in my view controller class like this:

    //button click method here
response = [lh userLogin : userEmail : userPass];
            if (response) {//do some action}

So, yeah, as you can see, i call a method, which then performs the download task asynchronously, and afterwards i check the return value immediately, which is "null", of course. So how do i synchronise the return value with dataTask, or check it completion any other way?

Already tried the dumb "while loop" and semaphore approach, both hanging the main thread, as expected. Tried something with notifications, but end up with nothing.

I'm pretty sure it has a damn simple solution, but can't get it.

Would be glad for any help.


Solution

  • Yes, you're missing some basics.

    You can't call a method that operates asynchronously and expect the answer immediately. The solution is to write the method to take a completion block. Then you pass the code that you want to execute in the completion block. The method call returns immediately, before the results are available, but the completion block code gets called once the download task has completed.

    I wrote a SO answer that include a sample app, but it's written in Swift. If you are brand-new to iOS development and are working in Objective-C you might find it hard to follow.

    If you are just learning iOS development you should think seriously about learning Swift. Apple makes it pretty clear that Swift is the future for iOS development. Learning Objective-C is useful as well, but I'd suggest putting your focus on Swift.