2017-03-26 38 views
1

私のアプリでフレンドリストを作成していますが、fetchfriendsはそのユーザーが友達であるユーザーのリストを作成し、ユーザーをフェッチしてから、情報。これはうまくいくようですが、なんらかの理由でフェッチユーザーが実行されてフェッチ先の友人が誰かにこれを手伝うことができますか?これは私のコードです。私は今ではコメントアウトされている条件文を試してみただけで、そのように2番目の関数を実行したことはありません。ファーストファンクションが最初に実行された後に呼び出される関数

override func viewDidLoad() { 
    super.viewDidLoad() 
    ref = FIRDatabase.database().reference() 


    friendsTableView.delegate = self 
    friendsTableView.dataSource = self 

    fetchfriends() 

    //if userspresent == true { 
    fetchuser() 
    // } 
    // Do any additional setup after loading the view. 
} 



    func fetchfriends() { 

    ref.child("users").child(userID!).child("friends").observeSingleEvent(of: .value, with: { (snapshot) in 
     if let value = snapshot.value as? NSDictionary { 

      let userName = value["username"] as? String ?? "" 
      let friendid = value["userid"] as? String ?? "" 

      self.userIds.append(friendid) 
      self.userspresent = true 
     print(userName, friendid) 
     } 
    }) 
} 

    // var index1:Int = 0 
    //if userspresent == true { 
func fetchuser() { 

    //let count = userIds.count 
    for index1 in 0...userIds.count-1 { 
     ref.child("users").child(userIds[index1]).observeSingleEvent(of: .value, with: { (snapshot) in 

     let value = snapshot.value as? NSDictionary 
     let user = User() 
     let userName = value?["username"] as? String ?? "" 
     let email = value?["email"] as? String ?? "" 
     let profileImageUrl = value?["profileImage"] as? String ?? "" 
     user.userName = userName 
     user.email = email 
     user.profileImageUrl = profileImageUrl 
     print(user) 
     self.users.append(user) 

     DispatchQueue.main.async { 
      self.friendsTableView.reloadData() 
     } 



     print(user.userName!, user.email!) 

     // print(snapshot) 
    }, withCancel: nil) 
    } 
} 
+0

コードでは、非同期アクションを実行することをお勧めします。それはすぐにfetchfriends()を終了し、バックグラウンドで行動を起こします。 fetchfriends()は、fetchfriends()で起こったアクションに、そのプリント直後に移動することを検討するべきです。 –

答えて

3

@Taylor Mは正しいです。これらは非同期ネットワーク操作であるため、最初に完了するものは確かにわかりません。 fetchuserfetchfriendsで生成されたデータに依存しているので、(つまり、userIdsの値があることを)あなたは単にfetchfriendsにパラメータとしてクロージャを追加することができます。

func fetchfriends (_ completion: ((Void) -> Void)?) { 
    ref.child("users").child(userID!).child("friends").observeSingleEvent(of: .value, with: { (snapshot) in 
    if let value = snapshot.value as? NSDictionary { 

     let userName = value["username"] as? String ?? "" 
     let friendid = value["userid"] as? String ?? "" 

     self.userIds.append(friendid) 
     self.userspresent = true 
     print(userName, friendid) 

     // call the closure function upon completion 
     completion?() 
    } 
}) 

を今、あなたはviewDidLoadは、単に行うfetchfriendsに呼び出すとき:

fetchfriends { 
    // this will be called when the friends are successfully fetched 
    self.fetchuser() 
} 
+0

ありがとうございました – lawndogg

0

何が起こっているかは、非同期ネットワークコールです。あなたはそのフェッチユーザーは次のようにあなたのコードがある場合は前に友人をフェッチ走っていると言ってに誤っている:あなたのobserveSingleEvent

override func viewDidLoad() { 
    ... 
    fetchfriends() 

    //if userspresent == true { 
    fetchuser() 
    // } 
} 

は、あなたがこの機能に firebaseは、そのイベントを観察した後を実行するためのクロージャを提供呼び出します。

したがって、observeSingleEventを呼び出すfetchfriends(最初)を呼び出します。 OSはこのネットワークコールをバックグラウンドスレッドに配置して作業を行い、ネットワークコールが終了すると、提供されたクロージャが実行されます。一方、メインスレッドでは、プログラムは実行され続け、observeSingeEventを呼び出して呼び出しを終了し、別のバックグラウンドスレッドに入れてプログラムを実行し続けるfetchuser(秒)を呼び出します。ほとんどの場合、fetchuserメソッドで記述されたクロージャが最初に実行されるように見えますが、そのネットワークは時間がかからず最初のものです。

+0

ありがとうございますが、fetchfriendsが終了するまでフェッチユーザーが実行されていないことを確認するにはどうすればよいですか? – lawndogg

+0

'fetchfriends'の' observeSingleEvent'呼び出しの終了時に 'fetchuser'呼び出しを行います。 –

+0

もっと柔軟にするには、[fetchfriends]メソッドに[closure](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html)を追加し、 'fetchuserあなたがコードを呼び出して、友人データを解析するクロージャーに入ります。 –

関連する問題