Jack Sierkstra Jack Sierkstra - 5 months ago 38
Objective-C Question

How to maintain a session in objective-c?

So i got the following problem:

I got a login viewcontroller and a form viewcontroller. On the login viewcontroller, i am sending a POST request to a PHP script which validates if the user has access. The script just returns an 1 or 0. So i can then choose to dismiss or maintain the viewcontroller. When the credentials are passed right, the user will see the form controller. This controller got a button to fetch a form.

The button to fetch the form, makes a POST request to another PHP script, which will return an XML document with the values of the user. I need a way to remember the username and password the user has passed through. So i can use them in another (view) controller.

Does anybody know a way to achieve this?

Answer

If you're using NSURLConnection, and the session is cookie based, this would automatically be done. So all you'd need to write would be similar to this

NSMutableURLRequest *request = nil;
request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://server.com/login.php"]];

NSString *post = [NSString stringWithFormat:@"username=%@&password=%@", @"<username>", @"<password>"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
[request setTimeoutInterval: 15];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:postData];

_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[_urlConnection start];

And you would have to implement the NSURLConnectionDelegate methods as well

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

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    //Oops! handle failure here
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    if (_statusCode >= 200 && _statusCode < 400) {
            //Things look ok
        NSString *responseString = [[[NSString alloc] initWithData:_responseData] autorelease];
        //Send this to an xml lib and parse
        }

    [_responseData release];
    _responseData = nil;
    [connection autorelease];
}

If you have some other information thats in the headers and which you need to send back with consequent requests, you can read it from the response like this

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSDictionary *headerFields = [(NSHTTPURLResponse*)response allHeaderFields]; //This would give you all the header fields;
    }
}

And set the header fields for the next request like this

    [request setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];

To save information, be it username and/or password or session information you can use NSUserDefaults

    //To save
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];

if (standardUserDefaults) {
    [standardUserDefaults setObject:@"<username>" forKey:@"username"];
    [standardUserDefaults setObject:@"<pass>" forKey:@"password"];
    [standardUserDefaults synchronize];
}

//To retrieve
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *val = nil;

if (standardUserDefaults) 
    val = [standardUserDefaults objectForKey:@"username"];

Lastly, it would be advisable to build a model to map the xml API with [Eg: a User class with username and password properties].

Google for Apple's docs on MVC.

Hope this helps!

Comments