Xcode iOS:检查用户是否已登录,如果未登录则显示不同的视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21202332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 04:33:46  来源:igfitidea点击:

Xcode iOS: check if user is logged in and show different views if not

iosxcodesessionloginnsuserdefaults

提问by el-flor

I'm coding an app where a logged in user has got a couple of extra functionalities than a non logged in user. Basically, I have more or less 5 tabs. When I launch the app, the user immediately gets the login page. He can decide to skip it. If he skips it, there'll only be 3 tabs for him. If he logs in successfully, there'll be 5.

我正在编写一个应用程序,其中登录用户比未登录用户获得了一些额外的功能。基本上,我有或多或少 5 个标签。当我启动应用程序时,用户立即获得登录页面。他可以决定跳过它。如果他跳过它,他将只有 3 个标签。如果他登录成功,就会有5个。

I already have my login page made. I just don't know how I can store a session if the user is logged in correctly, and only display a certain number of tabs if the user isn't. I come from PHP, I've just started learning Objective-C, so I'm looking for the same thing as $_SESSION in PHP, more or less.

我已经制作了登录页面。我只是不知道如何在用户正确登录的情况下存储会话,并且如果用户未正确登录,则仅显示一定数量的选项卡。我来自 PHP,我刚刚开始学习 Objective-C,所以我或多或少地在 PHP 中寻找与 $_SESSION 相同的东西。

So: if user logs in, store session, and show all the tabs. If he doesn't, only show a limited number of tabs. How should I approach this?

所以:如果用户登录,存储会话并显示所有选项卡。如果他不这样做,则只显示有限数量的选项卡。我应该如何处理这个问题?

采纳答案by Damien Pontifex

In terms of storing the session, I assume username and password is enough.

在存储会话方面,我假设用户名和密码就足够了。

You could store the username as you wish in NSUserDefaults or CoreData if you are using it. Storing a password is best using the keychain. SSKeychainmakes it easy to do this.

如果您正在使用它,您可以将用户名存储在 NSUserDefaults 或 CoreData 中。最好使用钥匙串存储密码。SSKeychain可以很容易地做到这一点。

[SSKeychain setPassword:password forService:myAppName account:userName]

You could store the fact they are logged in in-memory, but on app relaunch check by:

您可以将它们登录到内存中的事实存储起来,但在应用程序重新启动时通过以下方式进行检查:

NSString *password = [SSKeychain passwordForService:myAppName account:userName];
if (password != nil)
{
    // Logged in
}

If the user logs out, easy as deleting the password from the keychain by

如果用户退出,就像从钥匙串中删除密码一样简单

[SSKeychain deletePasswordForService:myAppName account:userName]

回答by JWKot

Session handling is done automatically when you use NSURLConnection, so you can store the users data in a Sesssion on the server.

会话处理在您使用 NSURLConnection 时自动完成,因此您可以将用户数据存储在服务器上的会话中。

What you might be looking for is called a Singleton design pattern (some people reject it, but it can be very handy). What you do is create one object that is available everywhere in your code. In this object you for example store a BOOL that indicates whether the user has logged in or not. For example: (I didn't run this, just to get the idea)

您可能正在寻找的称为单例设计模式(有些人拒绝它,但它可能非常方便)。您所做的是创建一个在您的代码中随处可用的对象。例如,在此对象中存储一个 BOOL,指示用户是否已登录。例如:(我没有运行这个,只是为了得到这个想法)

Mananger myManager* = [Manager sharedManager];
if(myManager.loggedIn){
    //Show 5 tabs
}else{
    //Show 3 Tabs
}

This code can be used in every class so you can always access your user's data. Manager would be a seperate class in this case that provides singleton functionality. Check out how to make one here: http://www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/

此代码可用于每个课程,因此您始终可以访问用户的数据。在这种情况下,Manager 将是一个单独的类,它提供单例功能。查看如何在这里制作:http: //www.johnwordsworth.com/2010/04/iphone-code-snippet-the-singleton-pattern/

回答by Edward Anthony

I'm gonna give you a comprehensive answer.

我会给你一个全面的答案。

Don't use NSUserDefaults as session it's a bad solution

不要使用 NSUserDefaults 作为会话,这是一个糟糕的解决方案

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

NSUserDefaults 数据未加密,可能会导致安全问题。

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.

创建一个类并将其命名为“EDUser”(如果需要,您可以选择其他名称)。
这个类将包含一个用户信息(当前用户或其他用户)。
更重要的是,这个类将能够让用户登录。

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: "[email protected]",
                         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())