在swift中首先运行第一个函数后调用的函数

时间:2017-03-26 19:52:26

标签: swift firebase firebase-realtime-database

我正在我的应用上创建一个朋友列表,fetchfriends创建一个用户列表,该用户是该用户,然后查看此列表并使用好友信息填充表格视图。这似乎可以正常工作,但出于某种原因fetch用户正在运行之前获取朋友可以有人帮我这个吗?这是我的代码。我甚至尝试了一个条件语句,现在已被注释掉了,它从未以这种方式运行第二个函数。

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

2 个答案:

答案 0 :(得分:3)

@Taylor M是对的。这些是异步网络操作,因此您无法确定首先完成哪一个。但是,由于fetchuser依赖于fetchfriends中生成的数据(即userIds中会有值),您只需将一个闭包作为参数添加到fetchfriends:< / p>

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

现在,当您在fetchfriends中致电viewDidLoad时,只需执行以下操作:

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

答案 1 :(得分:0)

正在发生的是异步网络呼叫。如果您的代码如下所示,在获取朋友之前说fetch用户正在运行是不正确的:

csvp.writeln()

override func viewDidLoad() { ... fetchfriends() //if userspresent == true { fetchuser() // } } 调用中,您为此函数提供了一个闭包,以便在 firebase观察到该事件后运行

所以你拨打observeSingleEvent(第一个)来调用fetchfriends。操作系统将此网络调用放在后台线程上以执行其工作,并在网络调用完成时,执行提供的闭包。同时,在主线程上,您的程序继续运行并调用observeSingleEvent(秒),它还调用fetchuser并将该调用和闭包放在不同的后台线程上,并且程序继续运行。很可能看起来好像首先运行用observeSingeEvent方法编写的闭包,因为该网络花费较少的时间并且是第一个回来的。