如何在iOS Swift中实现用户自动登录?

12

我正在使用云火力存储进行手机验证。在火力存储数据库中,我存储了用户的电话号码和UID。以下是我尝试用于手机号登录的代码:

  @IBAction func signUp(_ sender: Any) {
    // dismiss keyboard
    view.endEditing(true)   
    if sendOTP == false {
    let mobileNumber = "+91" + phoneNumberTextField.text!

    self.Userdefaults.set(mobileNumber, forKey: "mobileNumber")

    print("mobileNumber::::\(mobileNumber)")

    sendOTPCode()
    sendOTP = true

    } else {

        let codestring = OTPCodeTextField.text

        if codestring?.count == 6 {


            loginusingOTP(OTPtext: codestring!)


        } else {

            print("Enter 6 digit code")

        }

    }


func sendOTPCode() {

    let mymobilenumber = Userdefaults.string(forKey: "mobileNumber")
    PhoneAuthProvider.provider().verifyPhoneNumber(mymobilenumber!) { (verificationID, error) in


            self.Userdefaults.set(verificationID, forKey: "authVerificationID")

            if error != nil
            {
                print ("insde SendCode, there is error")



                print("error: \(String(describing: error?.localizedDescription))")

            } else {
                print ("code sent")


                self.phoneNumberTextField.allowsEditingTextAttributes = false



            }
    }

}

func loginusingOTP(OTPtext: String) {
    let db = Firestore.firestore()
    let verificationID = self.Userdefaults.string(forKey: "authVerificationID")

    let credential: PhoneAuthCredential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID!,
                                                                                  verificationCode: OTPtext)
    Auth.auth().signIn(with: credential)
    {
        (user, error) in
        if error != nil
        {
            print("error: \(String(describing: error?.localizedDescription))")
        }
        else if user != nil
        {

            print("Phone number: \(String(describing: user?.phoneNumber))")
            let userInfo = user?.providerData[0]
            print("Provider ID: \(String(describing: userInfo?.providerID))")

            var _: DocumentReference? = nil

            print("currentUser:::\(String(describing: currentUser))")

            db.collection("users").document(currentUser!).setData([
                "User_Phone_number": user?.phoneNumber as Any,
                "uid": currentUser as Any

            ]) { err in
                if let err = err {
                    print("Error writing document: \(err)")
                } else {
                    print("Document successfully written!")
                    if PrefsManager.sharedinstance.isFirstTime == false{


                        let when = DispatchTime.now() + 0
                        DispatchQueue.main.asyncAfter(deadline: when) {

                            self.performSegue(withIdentifier: "signUpToTabBar", sender: nil)

                        }


                    }else{
                        let when = DispatchTime.now() + 0
                        DispatchQueue.main.asyncAfter(deadline: when) {


                            let storyboard = UIStoryboard(name: "Start", bundle: nil)
                            let initialViewController = storyboard.instantiateViewController(withIdentifier: "onboardvc")
                            self.present(initialViewController, animated: true, completion: nil)

                        }
                    }



                }
            }

        } else {

            print("error::::::")

        }

    }

}

用户登录流程 - 首先用户输入手机号码,然后点击发送OTP,然后用户输入OTP代码,成功登录。由于用户第一次登录,需要填写用户详细信息页面,然后进入首页。如果已经登录的用户,在成功登录后将被重定向到主屏幕而不是用户详细页面。

我的问题是现在用户每次都要登录才能进入应用程序,我想让用户自动登录,除非用户注销。如何检查云Firestore中已登录用户的UID或电话是否存在或为新用户。

任何帮助都非常感谢...


您需要检查当前登录的用户。如果找不到用户,则将其带到登录屏幕。 - rv7284
用户登录后,您可以在UserDefaults中设置标志。每次需要检查标志是否为真,然后重定向到主屏幕(您需要在didFinishLaunchingWithOptions中编写代码)。否则,默认的登录屏幕将打开。在注销时,您需要从UserDefaults中删除此标志值。 - AbecedarioPoint
你完成解决方案了吗? - PPL
不行,@PPL,它没起作用。 - PvDev
@PvDev,你遇到了什么问题? - PPL
3个回答

11

让我简单介绍一下场景。

SwiftyUserDefaults 是在整个应用程序中存储 UserDefaults 的最佳库。

创建一个类似这样的扩展,

extension DefaultsKeys {
    static let username = DefaultsKey<String?>("username")
    static let phoneNo = DefaultsKey<String?>("phoneNo")
    static let islogin = DefaultsKey<Bool?>("islogin")
}

成功登录后,您可以像下面这样设置上述DefaultKeys的值,首先import SwiftyUserDefaults

Defaults[.username] = Your_User_Name
Defaults[.phoneno] = Your_Phone_No
Defaults[.islogin] = true

现在在您的第一个LoginViewController上,在viewDidLoad()方法中,请检查以下内容:

if Defaults[.islogin] == true {
    //Go to Home with animation false
}

请看这里,如果有任何疑问,请告诉我。

供参考。这只是一个场景,实际情况可能会因你的最终需求不同而有所不同。本答案可能会对你有帮助。


感谢您的回答!需要为SwiftUserDefaults安装Pod。我应该在哪里传递Defaults[.username] = Your_User_Name、Defaults[.phoneno] = Your_Phone_No和Defaults[.islogin] = true这个呢? - PvDev
这是您的数据,我仅取了三个字段供您参考。如果登录成功,Your_Phone_No 是用户输入的电话号码,islogin 应该为 true。 - PPL
安装 pod 时出错:pod 'SwiftyUserDefaults',:git => "https://github.com/radex/SwiftyUserDefaults.git" - PvDev
只需执行 pod 'SwiftyUserDefaults' 即可。 - PPL

8
针对Firebase(看起来也是FireStore),一旦用户在设备上验证通过,除非进行特定的登出(Auth.auth().signOut()),或者等待超长时间(不确定多久,可能是一个月),否则他们将自动“登录”到Firebase/Firestore的下一个会话。
检查用户是否已经登录。
在启动时(didFinishLaunchingWithOptions)设置一个Auth Listener,它将只触发一次并返回当前的Auth状态。
func addUserListener() {
    listenHandler = Auth.auth().addStateDidChangeListener { (auth, user) in
        if user == nil {
            // We are Logged Out of Firebase.
            // Move to Login Screen
        } else {
            // we are Logged In to Firebase.
            // Move to Main Screen
        }
  }

对于登录调用,您真的需要使用Auth Listener。如果某人有两个设备并在一个设备上注销,他们将从Firebase中注销,并且当您尝试进行Firebase调用时,第二个设备将崩溃,因为它仍然认为已登录。


这是更高效、更优选的做法,也是 Firebase 的方式。 - Cyril

3

更新您的登录凭据或将loggedIn标志设置为用户默认值

UserDefaults.standard.set("value", forKey: "username")
UserDefaults.standard.set("value", forKey: "password")
< p > (注意:建议不要直接存储密码,您可以将身份验证令牌存储在Userdefaults中;如果您想存储密码,请使用钥匙串)

然后从AppDelegate重定向到相应的页面:

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

   var initialViewController: UIViewController?
    let mainStoryboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    if let username = UserDefaults.standard.value(forKey: "username"), let password = UserDefaults.standard.value(forKey: "password") {
        initialViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeVC")
    } else {
        initialViewController = mainStoryboard.instantiateViewController(withIdentifier: "LoginVC")
    }
    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = initialViewController
    self.window?.makeKeyAndVisible()
   return true
}

请勿将用户凭据存储在UserDefaults中,为了安全起见,请将它们放入密钥链中。 - dr_barto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接