ios - 异步操作未按顺序完成

标签 ios swift asynchronous grand-central-dispatch

我有以下快速代码允许将用户联系人映射到网络服务器,然后显示在 TableView 中:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {


    dispatch_group_enter(self.dispatch_group)
    dispatch_group_async(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
         print("start 1")

        self.contacts = self.findContacts()

        dispatch_group_leave(self.dispatch_group)
        print("End 1")
    }

    dispatch_group_enter(self.dispatch_group)
    dispatch_group_async(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
        print("start 2")

        // Method to match contacts with Firebase db:
        self.mapContactsToPresentFriends(self.contacts, firebaseMainURL: self.firebaseMainURL, usersSyncID: "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de")

        dispatch_group_leave(self.dispatch_group)
        print("End 2")
    }


    dispatch_group_notify(self.dispatch_group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {
        print("start 3")

        // Final load of who is left of conacts (not user or friend)
        for contact in self.contacts {

            let phoneNumber = contact.phoneNumbers[0].value as! CNPhoneNumber

            self.friends.append(Friend(userName: "", phoneNumber: phoneNumber.stringValue, status: 0, name: contact.givenName, userID: ""))
        }

        for friend in self.friends {
            print(friend.status)
        }

        self.tableView!.reloadData()

    })
}

但是,注意 print("Start 1")、print("Start 2") 和 print("Start 3") 语句,日志将执行显示为:

start 2
start 1
End 2
End 1
start 3

这会产生不准确的结果。我需要这些异步任务按顺序发生(如打印语句所示),否则结果将毫无意义。

如何重新安排以确保其有效?

最佳答案

如果您真的希望这些事情按顺序发生,则不需要单独的 block 。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
    print("start 1")
    let contacts = self.findContacts()
    print("End 1")

    print("start 2")
    // Method to match contacts with Firebase db:
    self.mapContactsToPresentFriends(contacts, firebaseMainURL: self.firebaseMainURL, usersSyncID: "fdb17f3a-7b7d-4aa5-9a0b-b9fb33c349de")
    print("End 2")

    print("start 3")
    // Final load of who is left of conacts (not user or friend)
    var friends: [Friend] = []
    for contact in contacts {

        let phoneNumber = contact.phoneNumbers[0].value as! CNPhoneNumber

        friends.append(Friend(userName: "", phoneNumber: phoneNumber.stringValue, status: 0, name: contact.givenName, userID: ""))
    }

    for friend in friends {
        print(friend.status)
    }

    dispatch_async(dispatch_get_main_queue()) {
        // Any data/UI updates MUST be on the main queue
        self.friends = friends
        self.tableView!.reloadData()
    }
}

另外一些需要注意的事情:

  • 使用 dispatch_group_async 取代了对 _enter()_leave() 的需要。你不需要两者。 (如果你真的想使用组,你还需要 dispatch_group_notify 来完成工作。)
  • 当您分别调度每个 block 时,不需要外部调度(因为调用 _async() 很快)。
  • self.tableView.reloadData()(和 UI 更新)必须发生在主线程上,因此,您的数据源(例如 self.friends ) 也必须在主线程上更新。我已在上面的代码片段中对此进行了更改。

关于ios - 异步操作未按顺序完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37150319/

相关文章:

javascript - 是否可以使客户端 Javascript 按需同步

swift - UIBarButtonItem 值(forKey : key) cannot get view any more

ios - 每个 iOS 设备上的 NSDate 是否同步?

Swift & Firebase - 为用户信息拆分数据?

java - 检测 GWT 中的离线和在线状态

html - 如何在所有异步 http 调用完成之前显示加载指示器 - Angular

ios - 如何选择和突出显示像 UITableViewCell 这样的 UICollectionView?

iphone - 扩展教程 Material 时 entityForName 和 ManagedObjectContext 的问题

iOS 图表显示从 API 检索数据之前 - swift

ios - 我可以强制用户使用 hockeyapp 更新我的应用程序吗?