lucgian841
lucgian841

Reputation: 2002

Priority execution of methods i iOS

I'm developing an application that should login to a remote service in the first view controller I create a UI to insert username and password. When I press on the button login I make the following check:

The method to call the external class is the follow:

- (BOOL)loginSuccessWith:(NSString*)userName and:(NSString*)password {
    ConnectionHandler *connectionHandler = [[ConnectionHandler alloc]init];
    if ([connectionHandler startConnectionToServer:@"serverAddress" andUsername:userName withPassword:password andInstallationId:[[NSUserDefaults standardUserDefaults] objectForKey:@"instId"]]) {
        return YES;
    } else {
        return NO;
    }

}

As you can see if the method return YES or NO if the user can be logged or not. In the ConnectionHandler class I wrote the following code:

#import "ConnectionHandler.h"

@interface ConnectionHandler() {
    BOOL authenticated;
}
@end

@implementation ConnectionHandler

- (BOOL)startConnectionToServer:(NSString *)address andUsername:(NSString *)username withPassword:(NSString *)password andInstallationId:(NSString*) installationId {
    if (![self sendRequestToURL:address withMethod:@"POST" withUsername:username withPassword:password andInstallationId: installationId]) {
        NSLog(@"Impossibile connettersi");
        return NO;
    } else {
        if (authenticated) {
            return YES;
        } else {
            return NO;
        }
    }
}

- (id)sendRequestToURL:(NSString *)url withMethod:(NSString *)method withUsername:(NSString*)username withPassword:(NSString*)password andInstallationId:(NSString*)installationId {
    NSURL *finalURL = [[NSURL alloc]init];

    if ([method isEqualToString:@"POST"]) {
        finalURL = [NSURL URLWithString:url];
    } else {
        NSLog(@"Metodo no previsto");
    }

    NSString *post = [NSString stringWithFormat:@"username=%@&password=%@&installationId=%@", username, password, installationId];
    NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];

    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)postData.length];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
    [request setURL:finalURL];
    [request setHTTPMethod:method];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request setHTTPBody:postData];

    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
    if (connection) {
        [connection start];
    }
    return connection;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    self.responseData = [[NSMutableData alloc]init];

}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.responseData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    // Parsing della risposta dal server parlare con Giancarlo per vedere che tipo di risposta ottengo
    NSDictionary *json;
    NSError *err;

    json = [NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:&err];
    if (err) {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"AT Brain" message:@"Impossibile satbilire una connessione con il server" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
        [alert show];
    } else {
        NSString *error_code = [NSString stringWithFormat:@"%@", [json objectForKey:@"error_code"]];
        int success = [[json objectForKey:@"success"] intValue];
        NSString *error_desc = [NSString stringWithFormat:@"%@", [json objectForKey:@"error_desc"]];

        if ([self autenthicationOkWithErrorCode:error_code withSuccess:success andErrorDesc:error_desc]) {
            authenticated = YES;
        } else {
            authenticated = NO;
        }
    }
}

- (BOOL)autenthicationOkWithErrorCode:(NSString*)error_code withSuccess:(int)success andErrorDesc:(NSString*)error_desc {

    int errCode = [error_code intValue];

    if (success == 1) {
        return YES;
    } else if (success == 0) {
        if (errCode == 2) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"AT Brain" message:@"Controlla di aver inserito username, password e di avere un installationId" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            return NO;
        }
        if (errCode == 3) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"AT Brain" message:@"Credenziali non valide, inserisci username e password corrette" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            return NO;
        }
        if (errCode == 4) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"AT Brain" message:@"Utente non autorizzato ad accedere al servizio" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            return NO;
        }
        if (errCode == 5) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"AT Brain" message:@"L'utenza a cui stai cercando di accedere è già associata ad un utente diverso" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            return NO;
        }
        if (errCode == 6) {
            UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"AT Brain" message:@"Installation ID errato" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"OK", nil];
            [alert show];
            return NO;
        }
    }
    return NO;
}

I can connect to the server without problem, but before the - (void)connectionDidFinishLoading:(NSURLConnection *)connection is called it execute all the code in the - (BOOL)startConnectionToServer:(NSString *)address andUsername:(NSString *)username withPassword:(NSString *)password andInstallationId:(NSString*) installationId and it returns NO so the segue in the login view controller doesn't work because the method -(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender returns NO. So my problem is how to wait the execution of the method - (void)connectionDidFinishLoading:(NSURLConnection *)connection is done before execute the else section in method - (BOOL)startConnectionToServer:(NSString *)address andUsername:(NSString *)username withPassword:(NSString *)password andInstallationId:(NSString*) installationId? I hope you understand my issue and I hope you will help me to fix it, thank you

Upvotes: 0

Views: 150

Answers (1)

Rob Napier
Rob Napier

Reputation: 299345

NSURLConnection is asynchronous. You kick it off and it immediately returns. You get callbacks (such as connectionDidFinishLoading) when it completes. That's the point at which you can check for success and move onto the next step.

I assume that loginSuccessWith:and: is called on the main thread (this is a very strange name for a method; you probably meant loginWithUsername:password:). So it can't block waiting for a network request that may take a very long time to complete. You'd hang the entire UI.

The URL Loading System Programming Guide has a great deal of information on how to design this. Look first at NSURLSession, and if it doesn't meet your needs, then use the lower-level NSURLConnection. With NSURLSession, you can pass completion blocks that will run whenever the operation completes.

Upvotes: 4

Related Questions