我想知道,从Firebase数据库获取values
最安全的方法是什么?我问这个是因为我到处都是nil
,所以无法跟踪它们。例如,如果我采用这段代码,你应该怎么做?
例如,如果用户在离线时以某种方式访问应用,我会收到nil
并崩溃。
像这样,我注册用户并将值添加到Firebase数据库中:
guard let username = usernameField.text, let email = emailField.text, let password = passwordField.text else{
print("Successfully registered")
return
}
if connectedToNetwork() == true{
if passwordField.text == confirmPasswordField.text{
FIRAuth.auth()?.createUser(withEmail: email, password: password, completion: { (user: FIRUser?, error) in
if error != nil{
print(error)
return
}
guard let uid = user?.uid else{
return
}
let user = FIRAuth.auth()?.currentUser
user?.sendEmailVerification() { error in
if let error = error {
print(error.localizedDescription)
} else {
print("Email has been sent to you!")
}
}
//Successfully authenticated user
let ref = FIRDatabase.database().reference(fromURL: "https://snuspedia.firebaseio.com/")
let usersReference = ref.child("users").child(uid)
let reputation: Int = 0
let values = ["username": username, "email": email, "reputation": reputation] as [String : Any]// These are the values in Firebase database json tree which I get in next code part.
usersReference.updateChildValues(values, withCompletionBlock: {
(err, ref) in
if err != nil{
print(err)
return
}
print("User saved and logged in")
let mainStoryboard: UIStoryboard = UIStoryboard(name:"Main",bundle:nil)
let ProfileViewController: UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "ProfileViewController")
//Send the user to the LoginViewController
self.present(ProfileViewController, animated: true, completion: nil)
})
})
}else{
let view: MessageView
var config = SwiftMessages.Config()
view = MessageView.viewFromNib(layout: .StatusLine)
view.configureTheme(.error)
config.presentationStyle = .top
config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar)
view.configureContent(title: nil, body: "Passwords do not match!", iconImage: nil, iconText: nil, buttonImage: nil, buttonTitle: "Hide", buttonTapHandler: { _ in SwiftMessages.hide() })
SwiftMessages.show(config: config, view: view)
}
}else{
let view: MessageView
var config = SwiftMessages.Config()
view = MessageView.viewFromNib(layout: .StatusLine)
view.configureTheme(.error)
config.presentationStyle = .top
config.presentationContext = .window(windowLevel: UIWindowLevelStatusBar)
view.configureContent(title: nil, body: "The internet connection appears to be offline.", iconImage: nil, iconText: nil, buttonImage: nil, buttonTitle: "Hide", buttonTapHandler: { _ in SwiftMessages.hide() })
SwiftMessages.show(config: config, view: view)
}
就像这样,我尝试获取用户名和信誉以及个人资料图片:
self.loggedInUser = FIRAuth.auth()?.currentUser
//get the logged in users details
self.databaseRef.child("users").child(self.loggedInUser!.uid).observeSingleEvent(of: .value) { (snapshot:FIRDataSnapshot) in
//store the logged in users details into the variable
print(self.loggedInUser)
let snapshot = snapshot.value as! [String: AnyObject]
self.usernameLabel.text = snapshot["username"] as! String
if let reputation = snapshot["reputation"] {
self.reputationLabel.text = "\(reputation)"
} else {
print("reputation is nil")
}
if(snapshot["profileImage"] !== nil)
{
let databaseProfilePic = snapshot["profileImage"]
as! String
let data = try? Data(contentsOf: URL(string: databaseProfilePic)!)
self.setProfilePicture(self.profileImageView,imageToSet:UIImage(data:data!)!)
}
self.loadingIndicator.stopAnimating()
}
例如,在上一个代码中,每次进入视图时,即使我已{strong>启用 persistence
中的appDelegate
,它也会再次加载数据。< / p>
对我来说,似乎我做错了,因为我所做的print()
(我知道调试不对)输出了Optionals。
我如何摆脱它们?每个提示都受到高度重视。我应该将一些值存储到userDefaults
以防止出现错误吗?或者我应该使用OOP并为用户创建struct?
我必须说我读了很多关于他们但却找不到合适的答案。
答案 0 :(得分:1)
如果上述代码是在用户首次登录您的应用时运行,那么我强烈建议您存储他们的信息;你的对象是Defaults
。您只需将您的类符合NSCoding
并实现其协议即可。这样可以加快你的发布速度,因为你只需要进行一次异步调用;用于图像检索,与两个相反。
您必须手动更新这些值,但可以在func applicationDidEnterBackground(_ application: UIApplication)
或func applicationWillTerminate(_ application: UIApplication)
不建议将图片存储到Defaults
中,因此我建议您存储该网址,然后只需下载图片。
修改:
我还建议您将User
实施为单身,以便在整个应用中应用所做的任何更改,从而使维护更容易。有关详细信息,请参阅here
对于不是的情况,那么这就是我实现第二部分的方式
func online()
{
guard let user = FIRAuth.auth()?.currentUser else
{
print("User not FrB logged In")
return
}
//Have you implemented an = operator in your class? Correct me if I'm wrong but this may be doing a shallow copy instead of assigning the variables respectively. If you haven't then I'd recommend you implement a copy constructor to perform a deep copy
self.loggedUser = user
//get the logged in users details
self.databaseRef.child("users").child(user.uid).observeSingleEvent(of: .value) { (snapshot:FIRDataSnapshot) in
//store the logged in users details into the variable
print(self.loggedInUser)
guard let snapshot = snapshot.value as? [String:AnyObject], let userName = snapshot["username"] as? String, let reputation = snapshot["reputation"] as? String, let profilePicURL = snapshot["profileImage"] as? String
else
{
print("Error with FrB snapshot")
return
}
self.usernameLabel.text = userName
self.reputationLabel.text = reputation
let imageURL: URL = URL(string: profilePicURL)! // safe to unwrap here since we know it has a value
URLSession.shared.dataTask(with: imageURL, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in
guard let sessionData = data, error == nil else
{
print("Image download error")
print(error!.localizedDescription) // safe to unwrap because we know error!=nil
return
}
// If not performed in the background, it'll block the UI and your app may be terminated if the operation takes a while
DispatchQueue.main.async(execute: {
self.profileImage = UIImage(data: sessionData)!
self.loadingIndicator.stopAnimating() // stop animating after retrieving the image
})
}).resume()
}
}
我确定你可以折射另一种方法。干杯队友!