首先,最重要的是,这个问题是关于iOS,而不是android。希望它不会再次被标记为重复到android。
第二,为了清楚解释,这些是我对应用程序运行方式的意图:
注意:直到第2点我都可以做。我知道如何从firebase检索数据。问题出在第3点以后。
问题
我对堆栈溢出的解决方案进行了很多研究,并且我了解它与异步有关,而异步代码首先将在其中运行。但是,我找不到与shouldPerformSegue方法相关的单个解决方案。
虽然我尝试了completionHandler方法。但是,该代码段无法在该方法内返回true或false,因此无法确定是否应该执行segue。另外,只有当我需要将该用户ID传递到其他视图控制器时,才能在该方法中检索数据。
这是shouldPerformSegueWithIdentifier代码(如果格式化已关闭,请原谅我,因为我通常不会在堆栈溢出中问问题,但是我无能为力,因为这很烦我,因为我找不到解决方案经过一整天的梳理堆栈溢出。尽管不要介意“返回true”,因为在此期间我仍然需要访问其他视图控制器,因此,除了空检查之外,我现在将其设置为true。) :
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
let username : String = outUsername.text!
let password : String = outPassword.text!
if username.isEmpty && password.isEmpty {
let alert = UIAlertController(title: "Error", message: "Username and/or password cannot be empty", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
return false
} else {
db.collection("user").getDocuments() { (querySnapshot, err) in
if err != nil {
print("Error getting documents")
} else {
for document in querySnapshot!.documents {
let username02 : String = (document["username"] as? String)!
let password02 : String = (document["password"] as? String)!
if username02 == username && password02 == password {
self.userID = document.documentID
}
}
}
}
return true
}
}
答案 0 :(得分:0)
其他检查中的问题是:
您执行异步任务,因此,当您通过 else 检查时,会发生以下情况:在从 firebase 检索数据之前,您返回 true 。 >。
所以您需要做的是使用completionHandler或一些通知,然后将函数返回类型更改为void:
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?, completionHandler: @escaping ( _ shouldPerformSegue : Bool, _ userId : String) ->()) {
let username : String = outUsername.text!
let password : String = outPassword.text!
if username.isEmpty && password.isEmpty {
let alert = UIAlertController(title: "Error", message: "Username and/or password cannot be empty", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
completionHandler(false,"")
} else {
db.collection("user").getDocuments() { (querySnapshot, err) in
if err != nil {
print("Error getting documents")
} else {
for document in querySnapshot!.documents {
let username02 : String = (document["username"] as? String)!
let password02 : String = (document["password"] as? String)!
if username02 == username && password02 == password {
completionHandler(true,document.documentID)
}else{
completionHandler(false,"")
}
}
}
}
}
答案 1 :(得分:0)
我假设成功登录后您已经收到了数据(self.userID = document.documentID)。那么您可以通过多种方式使用该数据...
方法1:UserDefaults 成功登录后,将您的用户ID设置为UserDefaults。像
UserDefaults.standard.set(true, forKey: "userLoggedIn")
UserDefaults.standard.set(documentID, forKey: "userId")
UserDefaults.standard.synchronize()
和您可以返回的下一个homeViewController,例如
UserDefaults.standard.bool(forKey: "userLoggedIn") // true
UserDefaults.standard.string(forKey: "userId") //documentID
方法2:Segue
将接收到的值设置为登录ViewController的全局变量,并在performSegue中使用它。
致电您的Segue
self?.performSegue(withIdentifier: "loginToMain", sender: self)
自动执行方法,将全局值设置为homeViewController变量。我认为HomeViewController具有var userID。
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "loginToMain") {
if let target = segue.destination as? homeViewController
{
target.fromLogin = true
target.userId = self.userId
}
}
}
希望,它会有所帮助..
stackoverflow总是有用的
答案 2 :(得分:0)
因此,在尝试了无数天之后,终于能够使它正常工作,尽管加载速度有点慢,但是现在就可以了,因为它只是一个示例原型应用程序。如果您中的任何一个在从Firebase检索后遇到空人口,并且需要将该数据传递给另一个控制器,请按以下步骤操作:
按钮代码中的IBAction:
@IBAction func actLogin(_ sender: UIButton) {
let username : String = outUsername.text!
let password : String = outPassword.text!
if username.isEmpty && password.isEmpty {
let alert = UIAlertController(title: "Error", message: "Username and/or password cannot be empty", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .default, handler: nil))
present(alert, animated: true, completion: nil)
} else {
var userID : String = ""
var recordFound : Bool = false
db.collection("user").getDocuments() { (querySnapshot, err) in
if err != nil {
print("Error getting documents")
} else {
for document in querySnapshot!.documents {
let username02 : String = (document["username"] as? String)!
let password02 : String = (document["password"] as? String)!
if username02 == username && password02 == password {
userID = document.documentID
recordFound = true
}
}
if recordFound == true {
self.performSegue(withIdentifier: "nextCtrl", sender: userID)
} else {
let alert = UIAlertController(title: "Error", message: "Please enter a valid account credential.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Close", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
}
}
}
准备segue方法:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let tabBarCtrller = segue.destination as? UITabBarController, let userID = sender as? String {
// To retrieve from Firebase once user and password login is in place
let userID : String = userID
// To Book Now controller
let navCtrl = tabBarCtrller.viewControllers![0] as! UINavigationController
let bknctrl = navCtrl.topViewController as! BookNowScreen01
// To By Date controller
let navCtrl02 = tabBarCtrller.viewControllers![1] as! UINavigationController
let bdctrl = navCtrl02.topViewController as! DateDurationScreen01
// To By Room controller
let navCtrl03 = tabBarCtrller.viewControllers![2] as! UINavigationController
let brctrl = navCtrl03.topViewController as! RoomScreen01
// To View Bookings controller
let navCtrl04 = tabBarCtrller.viewControllers![3] as! UINavigationController
let vbctrl = navCtrl04.topViewController as! ViewBookings
bknctrl.userIDfromLogin = userID
bdctrl.userIDfromLogin = userID
brctrl.userIDfromLogin = userID
vbctrl.userIDfromLogin = userID
}
outUsername.text = ""
outPassword.text = ""
}