0

I'm making a URLRequest that sends attempted login information and waits for a response from the web service to find out if the user can/cannot log in.

The way I was hoping to do this was by having the user type in his username & password into two text fields and then press a button, which would call the function below. This function would start an NSURLSessionDataTask and construct a struct with the boolean success/failure of the login and an NSString with the corresponding error message (if any).

The problem is that my function returns the struct before my NSURLSessionDataTask's completion block has finished executing. Is there a way for me to force my program to wait until this task either times out or completes? Alternatively, can I push execution of the completion block onto the main thread & before the function returns?

Thanks! Please let me know if there are any clarifications I need to make!

(Also, I have seen some similar questions circulating around StackOverflow that mention GCD. Is this an overkill solution? None of those questions seem to be talking about quite the same thing, or do so on a level that is higher than my current understanding. I am still very new to Objective-C)

- (struct RequestReport) sendLoginRequest: (NSString*) username withPassword:  (NSString *) password

... (creating the request & setting HTTP body)

NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error){

    NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData: data options:0 error:nil];

    success = (BOOL)jsonObject[@"success"];
    statusText = (NSString *) jsonObject[@"errors"];

}];

[dataTask resume];

struct RequestReport rr;
rr.status = statusText;
rr.success = success;

return rr;
Dharmesh Kheni
  • 71,228
  • 33
  • 160
  • 165
13rave
  • 135
  • 2
  • 15
  • The typical design pattern for this type of problem is to pass a callback block that is executed when the task returns and show a loading indicator in the mean time. The method should be void, and the callback block executed in the callback from the NSURLSessionDataTask. – DBoyer Oct 30 '14 at 23:16
  • Aw, I hate having to write more methods :P I was hoping there was another solution, especially since my program does effectively have to "block" until the user is logged in. For security reasons, there are no features available to non-logged users. – 13rave Oct 30 '14 at 23:17
  • Oh wait, you're not saying to write another method. A callback block? So like, passing in a delegate function (not sure what it's called in Objective-c) as a parameter to the login function? – 13rave Oct 30 '14 at 23:19
  • That is the typical situation for most apps on the app store. If you are new to networks calls on iOS, I highly recommend you use AFNetworking or another 3rd party framework to do most of the legwork for you, or better yet the Parse SDK if you are using Parse for your backend. I very rarely write my own networking code since there are such great open-source solutions out there. – DBoyer Oct 30 '14 at 23:24
  • A block is not technically a method its just a chunk of code that can be moved around by a variable. – DBoyer Oct 30 '14 at 23:25

1 Answers1

4

Your method should look like this:

- (void) sendLoginRequest:(NSString*) username withPassword:(NSString *) password callback:(void (^)(NSError *error, BOOL success))callback
    {
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request completionHandler: ^(NSData *data, NSURLResponse *response, NSError *error){
        if (error) {
            // Handle error
        }
        else {
           callback(error, YES);
       }
  }];

    [dataTask resume];

}

Call this method like so:

[self sendLoginRequest:@"myUsername" password:@"password" callback:^(NSString *error, BOOL success) {
    if (success) {
         NSLog(@"My response back from the server after an unknown amount of time";
    }
}

See Apple's Programming with Objective-C for more reading on blocks and fuckingblocksyntax.com for how to declare blocks.

Morgan Chen
  • 1,137
  • 7
  • 18
DBoyer
  • 3,062
  • 4
  • 22
  • 32