2017-08-16 7 views
0
//Just a struct to save information about the User 
var user = AppUser() 

override func viewDidLoad() { 
    super.viewDidLoad() 

//Verify if user is logged in 
    verifyUser() 
    user.email = "blabla" 

    print("viewdidload user: \(user)") 

} 

override func viewDidAppear(_ animated: Bool) { 
    super.viewDidAppear(true) 

    print("viewdidappear user: \(user)") 

} 

func verifyUser() { 

    print("verify user called") 

    //Log in verification 
    guard let userID = Auth.auth().currentUser?.uid else { 
     perform(#selector(handleLogOut), with: nil, afterDelay: 0) 

     print("nil user") 

     return 
    } 

    ref.child("users").child(userID).observeSingleEvent(of: .value, with: { (snapshot) in 
     if let dictionary = snapshot.value as? [String: AnyObject] { 
      self.user = AppUser(dictionary: dictionary) 

      print(self.user) 
     } 
    }) { (error) in 
     print(error.localizedDescription) 
    } 
} 

コンソール:viewDidLoad()funcでFirebaseのデータベースを正しく読み込むには?

verify user called 


viewdidload user: AppUser(id: nil, name: nil, email: 
Optional("blabla"), completedRegister: nil, FULLUser: nil) 


viewdidappear user: AppUser(id: nil, name: nil, email:     
Optional("blabla"), completedRegister: nil, FULLUser: nil) 


AppUser(id: nil, name: nil, email: Optional("[email protected]"),  
completedRegister: Optional(false), FULLUser: Optional(false)) 

質問は簡単です。誰かが、データベース情報で「ユーザの確認」と「ユーザ」の間に"print("viewDidLoad user:....")"がどのように印刷されているかを説明することはできますか?

問題は、何らかの理由で関数がviewDidLoadでユーザーの情報を取得しようとしたときに情報が取得されず、値がまだnilである場合です。それは時間の問題ですか? ...

は私が機能verifyUser()の後にループを入れてみましたが、それは決して

out: 

    while user.email == nil { 
      print("Waiting...") 
     } 

を取得していないので、質問に

感謝のthats!

編集用Anas Menhar これは私の構造体です。なぜNSObjectである方が良いのでしょうか? 私は(1つの空)INITS異なる2を行うことができますので、私は構造体を行なったし、私はそれだけで印刷した辞書を印刷する場合NSObjectのは、何らかの理由でHitesh

ため

struct AppUser { 
var id: String? 
var name: String? 
var email: String? 

var completedRegister: Bool? 

var FULLUser: Bool? 

init(dictionary: [String: Any]) { 
    self.id = dictionary["id"] as? String 
    self.name = dictionary["name"] as? String 
    self.email = dictionary["email"] as? String 

    self.completedRegister = Bool((dictionary["completedRegister"] as? String)!) 

    self.FULLUser = Bool((dictionary["FULLUser"] as? String)!) 

} 
init() { 
    self.id = nil 
    self.name = nil 
    self.email = nil 

    self.completedRegister = nil 

    self.FULLUser = nil 

} 
} 

編集をさせて頂いていませんでしたユーザが情報を完了したのと同じ時間。すべての終わりに。

+0

あなたは辞書= snapshot.value'を聞かせて '印刷することがありますか?これを追加できますか? – Hitesh

+0

AppUserのモーダルクラスを表示してください。クラスのようにする必要があります。ユーザー:NSObject { var id:String? var name:String? var email:String? var imageURL:String? }また、クラスの利点である user.setValuesForKeys(辞書) –

答えて

1

viewDidLoad()は、"viewdidload user: \(user)"を印刷する前にverifyUser()を呼び出しています。 verifyUser()のすべてが印刷前に終了します(ネットワークコールを除く)。だからここ

はあなたのために発生するイベントのシーケンスです:

  1. super.viewDidLoad()
  2. verifyUser()verifyUser()
  3. 印刷であるverifyUser()
  4. ガード文である
  5. print文と呼ばれています声明でviewDidLoad()
  6. いつでもそのコールが終了 - .observeSingleEventOfのため閉鎖内部super.viewDidAppear()

すべてで

  • プリントは4の後、いくつかのポイントが発生します。通話が終了したら何かしたい場合は、それをクロージャーに入れてください。

    このように:私は、コメントを追加しました

    ref.child("users").child(userID).observeSingleEvent(of: .value, with: { (snapshot) in 
        if let dictionary = snapshot.value as? [String: AnyObject] { 
         self.user = AppUser(dictionary: dictionary) 
         //***handle stuff that needs the user here 
         print(self.user) 
        } else { 
         //***handle getting no data for the user or data that is not [String: AnyObject] 
        } 
    }) { (error) in 
        //***handle any errors here 
        print(error.localizedDescription) 
    } 
    

    場所は、その要求が完了したときに、潜在的に呼び出されることになる場所です。

    サイドノート:AppUserのためにStructを使用する場合は、構造とクラスの違いを知っておいてください。あなたはAPPUSERという名前のクラスを持っている可能性があり、異なるが、このようINITS 2ています

    class AppUser { 
        var id: String? 
        var name: String? 
        var email: String? 
        var completedRegister: Bool? 
        var FULLUser: Bool? 
    
        ///initialization from a dictionary 
        init(dictionary: [String: Any]) { 
         id = dictionary["id"] as? String 
         name = dictionary["name"] as? String 
         email = dictionary["email"] as? String 
    
         if let completed = dictionary["completedRegister"] as? String { 
          if completed == "true" { 
           completedRegister = true 
          } else if completed == "false" { 
           completedRegister = false 
          } 
         } 
    
         if let fullUser = dictionary["FULLUser"] as? String { 
          if fullUser == "true" { 
           FULLUser = true 
          } else if fullUser == "false" { 
           FULLUser = false 
          } 
         } 
        } 
    
        ///initialization without a dictionary 
        init() { 
         //dont need to set any variables because they are optional 
        } 
    } 
    

    let user1 = AppUser(dictionary: ["id": "12342", 
              "name": "John Doe", 
              "email": "[email protected]", 
              "completedRegister": "true", 
              "FULLUser": "true"]) 
        ///user1 properties: 
        id: Optional("12342") 
        - some: "12342" 
        name: Optional("John Doe") 
        - some: "John Doe" 
        email: Optional("[email protected]") 
        - some: "[email protected]" 
        completedRegister: Optional(true) 
        - some: true 
        FULLUser: Optional(true) 
        - some: true 
    

    let user2 = AppUser() 
    ///user2 properties: none 
    
  • +0

    も使用してください。構造体が値型でありクラスが参照型であるという主な違いはありませんか?だから、私の場合、構造体はもっとうまく動作しませんでしたか?最後に、viewDidLoadコードの残りの部分の後にネットワークの問題が発生するのはなぜですか?ありがとうございました!! – Alexis

    +0

    はい、そうです。参照型であるクラスは、後で機能が拡張されるにつれて、それらを少し動的にします。ネットワーク通話は、作成した順序で開始されますが、必ずしもその順序で完了する必要はありません。あなたが10MBの高解像度の写真と500kbの低解像度の写真をダウンロードしているとします。あなたはどんな順序ででもそれらを始めることができますが、(それらが同期して実行されない限り)500kbがおそらく最初に終了します。 – erdos

    関連する問題