从Firebase检索值的最安全方法

时间:2016-10-04 18:13:44

标签: ios swift firebase firebase-realtime-database

我想知道,从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?

我必须说我读了很多关于他们但却找不到合适的答案。

1 个答案:

答案 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()
    }
}

我确定你可以折射另一种方法。干杯队友!