即使关闭应用程序,如何保持用户登录?我正在使用 swift 3 和 Firebase
Posted
技术标签:
【中文标题】即使关闭应用程序,如何保持用户登录?我正在使用 swift 3 和 Firebase【英文标题】:how to keep a user login even if they close the app? I'm using swift 3, and Firebase 【发布时间】:2017-05-11 17:50:16 【问题描述】:我是编码和堆栈溢出的新手,我试图让用户即使在关闭应用程序后也保持登录状态。我也不希望他们总是看到登录屏幕。即使用户关闭应用程序并重新打开应用程序,我该如何保持用户登录。我正在使用 Swift 3.0、Xcode 8 和 Firebase。
import UIKit
import Firebase
import SwiftKeychainWrapper
class LoginViewController: UIViewController
@IBOutlet weak var emailField: UITextField!
@IBOutlet weak var pwField: UITextField!
override func viewDidLoad()
super.viewDidLoad()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(LoginViewController.dismissKeyboard))
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
func dismissKeyboard()
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
@IBAction func loginPressed(_ sender: Any)
guard emailField.text != "", pwField.text != "" else return
FIRAuth.auth()?.signIn(withEmail: emailField.text!, password: pwField.text!, completion: (user, error) in
if let error = error
print(error.localizedDescription)
if user != nil
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabBarViewController")
self.present(vc, animated: true, completion: nil)
)
下面是我的 UsersViewController 代码,它有注销按钮
import UIKit
导入 Firebase
类用户视图控制器:UIViewController、UITableViewDelegate、UITableViewDataSource
@IBOutlet weak var tableview: UITableView!
var user = [User]()
override func viewDidLoad()
super.viewDidLoad()
retrieveUsers()
func retrieveUsers()
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrderedByKey().observeSingleEvent(of: .value, with: snapshot in
let users = snapshot.value as! [String : AnyObject]
self.user.removeAll()
for (_, value) in users
if let uid = value["uid"] as? String
if uid != FIRAuth.auth()!.currentUser!.uid
let userToShow = User()
if let fullName = value["full name"] as? String, let imagePath = value["urlToImage"] as? String
userToShow.fullName = fullName
userToShow.imagePath = imagePath
userToShow.userID = uid
self.user.append(userToShow)
self.tableview.reloadData()
)
ref.removeAllObservers()
func numberOfSections(in tableView: UITableView) -> Int
return 1
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableview.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! UserCell
cell.nameLabel.text = self.user[indexPath.row].fullName
cell.userID = self.user[indexPath.row].userID
cell.userImage.downloadImage(from: self.user[indexPath.row].imagePath!)
checkFollowing(indexPath: indexPath)
return cell
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return user.count
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let uid = FIRAuth.auth()!.currentUser!.uid
let ref = FIRDatabase.database().reference()
let key = ref.child("users").childByAutoId().key
var isFollower = false
ref.child("users").child(uid).child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: snapshot in
if let following = snapshot.value as? [String : AnyObject]
for (ke, value) in following
if value as! String == self.user[indexPath.row].userID
isFollower = true
ref.child("users").child(uid).child("following/\(ke)").removeValue()
ref.child("users").child(self.user[indexPath.row].userID).child("followers/\(ke)").removeValue()
self.tableview.cellForRow(at: indexPath)?.accessoryType = .none
if !isFollower
let following = ["following/\(key)" : self.user[indexPath.row].userID]
let followers = ["followers/\(key)" : uid]
ref.child("users").child(uid).updateChildValues(following as Any as! [AnyHashable : Any])
ref.child("users").child(self.user[indexPath.row].userID).updateChildValues(followers)
self.tableview.cellForRow(at: indexPath)?.accessoryType = .checkmark
)
ref.removeAllObservers()
func checkFollowing(indexPath: IndexPath)
let uid = FIRAuth.auth()!.currentUser!.uid
let ref = FIRDatabase.database().reference()
ref.child("users").child(uid).child("following").queryOrderedByKey().observeSingleEvent(of: .value, with: snapshot in
if let following = snapshot.value as? [String : AnyObject]
for (_, value) in following
if value as! String == self.user[indexPath.row].userID
self.tableview.cellForRow(at: indexPath)?.accessoryType = .checkmark
)
ref.removeAllObservers()
@IBAction func logOutPressed(_ sender: Any)
do
try FIRAuth.auth()?.signOut()
if FIRAuth.auth()?.currentUser == nil
// Remove User Session from device
UserDefaults.standard.removeObject(forKey: "uid")
UserDefaults.standard.synchronize()
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginVC") as! LoginViewController
catch let signOutError as NSError
// handle logout error
扩展 UIImageView
func downloadImage(from imgURL: String!)
let url = URLRequest(url: URL(string: imgURL)!)
let task = URLSession.shared.dataTask(with: url)
(data, response, error) in
if error != nil
print(error!)
return
DispatchQueue.main.async
self.image = UIImage(data: data!)
task.resume()
【问题讨论】:
【参考方案1】:Firebase 身份验证可以为您处理此问题。与 Firebase 数据库一样,Auth 通过设置侦听器来工作。您可以像这样在 App Delegate 中监听现有用户:
final class AppDelegate: UIResponder, UIApplicationDelegate
private let auth = FIRAuth.auth()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
auth?.addStateDidChangeListener [weak self] (_, user) in
if let user = user
// user is already logged in
else
// user is not logged in
【讨论】:
我会在哪里添加这个? 我会像我一样将它放在 App Delegate 中,这样您就可以在状态发生变化时更改窗口的根视图控制器。 在您关闭应用程序后仍然无法让他们保持登录状态。 确实如此。如果登录成功,Firebase 身份验证就会保留用户。 我需要在评论部分放一些东西才能让它工作吗?【参考方案2】:当用户成功登录后,将他们的 UID 放入 UserDefaults 以存储会话,如下所示:
UserDefaults.standard.set(FIRAuth.auth()!.currentUser!.uid, forKey: "user_uid_key")
UserDefaults.standard.synchronize()
然后,无论您的应用加载的第一个 View Controller 是什么,检查 viewDidAppear()
中的那个键,如下所示:
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
// Check if the user is logged in
if UserDefaults.standard.object(forKey: "user_uid_key") != nil
// send them to a new view controller or do whatever you want
将 UserDefaults 放在您注册/登录用户的 IBAction/Function 的成功块中,如下所示:
FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: (user, error) in
if user != nil
// Login success
// Saves User UID to UserDefaults
UserDefaults.standard.set(FIRAuth.auth()!.currentUser!.uid, forKey: "USER_KEY_UID")
UserDefaults.standard.synchronize()
else
// login error
)
用户注销时删除 UserDefault:
@IBAction func logoutButtonPressed(sender: UIButton!)
do
try FIRAuth.auth()?.signOut()
if FIRAuth.auth()?.currentUser == nil
// Remove User Session from device
UserDefaults.standard.removeObject(forKey: "USER_KEY_UID")
UserDefaults.standard.synchronize()
let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginVC") as! LoginVC
present("TheVCYouWantToSendTheUserTo", animated: true, completion: nil)
catch let signOutError as NSError
// handle logout error
更新:
您忘记在登录函数中包含 UserDefaults。这就是为什么它会给你一个错误。将此添加到您的登录 IBAction。
@IBAction func loginPressed(_ sender: Any)
guard emailField.text != "", pwField.text != "" else return
FIRAuth.auth()?.signIn(withEmail: emailField.text!, password: pwField.text!, completion: (user, error) in
if let error = error
print(error.localizedDescription)
// You forgot to save User UID to UserDefaults here...
UserDefaults.standard.set(FIRAuth.auth()!.currentUser!.uid, forKey: "uid")
UserDefaults.standard.synchronize()
if user != nil
let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabBarViewController")
self.present(vc, animated: true, completion: nil)
)
【讨论】:
我在哪里放置用户默认代码?还是在同一节下 我更新了上面的代码,使其更具可读性。看看这是否适合你 Firebase 身份验证已经在没有 UserDefaults 的应用启动时持续存在。 它的工作原理就像它会自动转到视图控制器但是如果我按下注销这将带我回到登录页面它会自动再次登录我该如何解决这个问题以便如果我注销它不会自动登录 对于删除用户默认值的代码,我是将其放在 loginviewcontroller 代码中还是注销按钮所在的位置?以上是关于即使关闭应用程序,如何保持用户登录?我正在使用 swift 3 和 Firebase的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 aws amplify 保持用户登录 react-native
我正在尝试使用 Framework-7 Vuejs 创建一个应用程序。即使在使用 Firebase 退出应用程序后,我也想让我的用户保持登录状态