2016-10-04 20 views
0

Firebaseデータベースからvaluesを取得する最も安全な方法は何ですか?私はnilをどこにでも持っているので、これを尋ねます。そして、それを追跡することは不可能です。たとえば、私がこのコードを取ったら、どうすればいいのですか?Firebaseから値を取得する最も安全な方法

たとえば、ユーザーが何らかの理由でオフラインでアプリにアクセスした場合、私はnilを取得してクラッシュします。このよう

、私は、ユーザーを登録してFirebaseデータベースに値を追加します。たとえば、

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

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) 
     } 

そして、このように、私は、ユーザーのユーザー名と評判とプロフィール画像を取得しよう最後のコードでは、私がビューに行くたびに、が有効になっていても、persistenceappDelegateに設定してもデータを再度ロードします。

私には、すべてprint()(これは私が知っているデバッグするのは正しくありません)の出力がオプションであるため、すべて間違っているようです。

どうすれば削除できますか?すべてのヒントは高く評価されています。いくつかのエラーを防ぐために、値の一部をuserDefaultsに保存する必要がありますか?または、私はOOPを使用して、ユーザー用の構造体を作成する必要がありますか?

私はそれらについて多くのことを読んだことがありますが、良い答えを見つけることはできません。

+0

あなたのアプリがクラッシュするのは残念だと思っていますが、コード内の特定の場所が無限になっていることを知らずに助けが難しいでしょう。一般的に、[最小限のアプリで問題を再現](http://stackoverflow.com/help/mcve)し、ここでそれを共有すると、最良の結果が得られます。 –

+0

私はnilsを指摘するように頼まなかった。私は選択肢を取り除く方法と、Firebaseからデータを取得する最良の方法を知りたいと思っていました。 –

答えて

1

ユーザーが初めてアプリにログインしたときに上記のコードが実行される場合は、その情報を保存することを強くおすすめします。あなたのオブジェクトは、Defaultsにあります。クラスをNSCodingに準拠させ、そのプロトコルを実装するだけです。 1つの非同期呼び出しを作成するだけでよいので、これは起動を高速化します。画像検索のために、2つとは対照的に。簡単func applicationDidEnterBackground(_ application: UIApplication)またはfunc applicationWillTerminate(_ application: UIApplication)

のいずれかで行うことができたことがDefaultsに画像を保存することをお勧めではありませんけれどもあなたはこれらの値を手動で更新する必要があると思います

ので、私はあなたがダウンロードするだけで、その後URLを保存お勧めします画像。

編集: 私も行われた変更は、それが簡単に維持すること、したがって、あなたのアプリ全体で適用されているように、あなたがシングルトンとしてあなた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() 
    } 
} 

私はあなたが他の方法を屈折することができます確信を実装したい方法です。歓声メイト!

+0

まずは、詳細な回答ありがとうございます。しかし、私はいくつかの質問があります。あなたは 'UIImageView '型に' UIImage'型の値を割り当てることができますか? 第2に、私はあなたがこれを安全に行うのが好きです。このように私は少なくとも何かが無ければクラッシュすることはありません。しかし、出力は何らかの理由で "FrBスナップショットのエラー"ですが、これらの値がデータベースに存在することを確信しています。 –

+0

問題はありません。あなたは 'yourImageView.image = yourImage'を実行してイメージを割り当てることができます。次に、 'FIRAuth.auth()?currentUser'は、あなたのアプリにログインしているユーザのトークンであるかどうかをチェックします。そのトークンはあなたの電話には存在しないので、失敗します。ユーザを作成した後、 'FIRAuth.auth()?。signIn(withEmail:)'ユーザが必要です。これにより、トークンがあなたのアプリに保存されます。このトークンを使用して、後で存在を確認することができます。そして、あなたが '試してみて! FIRAuth.auth()?signOut() 'の場合、トークンは' nil'に戻されます – eshirima

+0

しかし、それは存在します。私はサインインして、トークンを出力しようとしましたが、それはそれを印刷しました。 –

関連する問題