How to maintain a session in objective-c?

后端 未结 4 1336
鱼传尺愫
鱼传尺愫 2020-12-29 16:45

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 whic

相关标签:
4条回答
  • 2020-12-29 17:06

    Create a "model" object for your program (have a look at the model-view-controller pattern, which is ubiquitous in cocoa), then in your login controller, store username and password in the model; then, from wherever you need access those data, you read them from the model.

    0 讨论(0)
  • 2020-12-29 17:08

    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!

    0 讨论(0)
  • 2020-12-29 17:21

    I'm gonna give you a comprehensive answer, with Swift.

    Don't use NSUserDefaults and don't store password it's a bad solution

    NSUserDefaults data is not encrypted, it may cause security issue.

    Let's create a structured user class instead

    When the user logged in, you will need to make sure you have access to user data throughout the app so you can get the data on any screen when you need it.

    To achieve this, we need to make a great structure to organize this properly. Remember that current user and another users are both "user" so we will use the same class.

    Create a class and name it "EDUser" (you can choose other name if you want).
    This class will contain a user information (either current user or other user).
    More than that, this class will have capability to log the user in.

    Here's a picture of what the class might look like:

    class EDUser {
        var firstName: String
        var lastName: String?
        var birthDate: NSDate?
    
        init(firstName: String, lastName: String?, birthDate: NSDate?) {
            self.firstName = firstName
            self.lastName = lastName
            self.birthDate = birthDate
        }
    }
    
    // MARK: - Accessor
    
    extension EDUser {
        class var currentUser: EDUser? {
            get {
                return loadCurrentUserFromDisk()
            }
            set {
                saveCurrentUserToDiskWithUser(newValue)
            }
        }
    }
    
    // MARK: - Log in and out
    
    extension EDUser {
        class func loginWithUsername(username: String,
                               andPassword password: String,
                               callback: (EDUser?, NSError) -> Void) {
            // Access the web API
            var parameters = [
                "username": username,
                "password": password
            ]
            YourNetworkingLibrary.request(.POST,
                              "https://api.yourwebsite.com/login",
                              parameters: parameters).responseJSON { 
                response in
    
                if response.statusCode == .Success {
                    let user = EDUser(firstName: response["firstName"],
                           lastName: response["lastName"],
                           birthDate: NSDate.dateFromString(response["birthDate"]))
                    currentUser = user
                    callback(currentUser, nil)
                } else {
                    callback(nil, yourError)
                }
            }
        }
    
        class func logout() {
            deleteCurrentUserFromDisk()
        }
    }
    
    // MARK: - Data
    
    extension EDUser {
        class private func saveCurrentUserToDiskWithUser(user: EDUser) {
            // In this process, you encode the user to file and store it
        }
    
        class private func loadCurrentUserFromDisk() -> EDUser? {
            // In this process, you get the file and decode that to EDUser object
            // This function will return nil if the file is not exist
        }
    
        class private func deleteCurrentUserFromDisk() {
            // This will delete the current user file from disk
        }
    }
    
    // MARK: - Helper
    
    extension NSDate {
        class func dateFromString(string: String) -> NSDate {
            // convert string into NSDate
        }
    }
    

    Use Case

    Now with everything in place, we can use it like this

    Non-blocking logging in process

    EDUser.loginWithUsername(username: "edward@domain.com",
                             password: "1234") {
        user, error in
    
        if error == nil {
            // Login succeeded
        } else {
            // Login failed
        }
    }
    

    Logging out

    EDUser.logout()
    

    Check whether the user is logged in

    if EDUser.currentUser != nil {
        // The user is logged in
    } else {
        // No user logged in
        // Show the login screen here
    }
    

    Get current user data on any screen

    if let currentUser = EDUser.currentUser {
        // do something with current user data
    }
    

    Store other user as object

    let user = EDUser(firstName: "Edward",
                      lastName: "Anthony",
                      birthDate: NSDate())
    
    0 讨论(0)
  • 2020-12-29 17:28

    Yeah ASI HTTP Request is derived basically from NSURL class only..u need not worry about HTTP call back.just store those values in plist of use sqlite for complex and huge data storage purpose

    0 讨论(0)
提交回复
热议问题