2

在 Xcode 9 / Swift 4 中使用 Google APIs Client Library for Objective-C for REST:为什么 service.executeQuery 在线程完成之前返回线程完成通知?我一直在尝试各种方法,但我坚持使用以下代码,在线程完成之前返回通知。请参阅下面的代码、实际输出和我希望看到的内容(线程完成后会发出通知)。我究竟做错了什么?谢谢

func myFunctionTest () {
    let workItem = DispatchWorkItem {
                                  self.service.executeQuery(query,
                                  delegate: self,
                                  didFinish: #selector(self.displayResultWithTicket2b(ticket:finishedWithObject:error:))
                                  )
    }

    let group = DispatchGroup()
    group.enter()
    group.notify(queue: service.callbackQueue) {
        print("************************** NOTIFY MAIN THREAD *************************************")
    }
    service.callbackQueue.async(group: group) {
        workItem.perform()
    }
    group.leave()
}

@objc func displayResultWithTicket2b(ticket : GTLRServiceTicket,
                                     finishedWithObject messagesResponse : GTLRGmail_ListMessagesResponse,
                                     error : NSError?) {
    //some code to run here
    print("************************** 02.displayResultWithTicket2b ***************************")
}

输出

****************************** 通知主线程 ********************* ****************** ************************** 02.displayResultWithTicket2b ***** ************************

我所期望的 = 线程完成时会发出线程通知

****************************** 02.displayResultWithTicket2b ********************* ****** ****************************** 通知主线程 *************** ************************

4

1 回答 1

1

问题是您正在处理异步 API,并且您leave在完成提交请求时正在调用。leave()调用必须在调用的完成处理程序或选择器方法内executeQuery。如果您要坚持使用这种基于选择器的方法,则必须将调度组保存在某个属性中,然后displayResultWithTicket2b调用leave

executeQuery如果您使用基于块/闭包完成处理程序的API 再现,而不是基于选择器的 API,这会容易得多。然后你可以把它移到leave块/闭包完成处理程序中,你就完成了。如果您使用基于块的实现,它不仅消除了将调度组保存在某些属性中的需要,而且可能完全消除了对组的需要。

此外,回调队列可能不是为您添加自己的任务而设计的。它是库将用于其回调的队列(完成块和/或委托方法将在其上运行的队列)。只需调用executeQuery,库就会负责在该队列上运行回调。不需要DispatchWorkItem

session.executeQuery(query) { ticket, object, error in
    // do whatever you need here; this runs on the callback queue

    DispatchQueue.main.async {
        // when you need to update model/UI, do that on the main queue
    }
}

我唯一一次使用调度组是,如果我正在执行一系列查询并且需要知道它们何时完成:

let group = DispatchGroup()

for query in queries {
    group.enter()

    session.executeQuery(query) { ticket, object, error in
        defer { group.leave() }

        // do whatever you need here; this runs on the callback queue
    }
}

group.notify(queue: .main) {
    // do something when done; this runs on the main queue
}
于 2018-02-04T16:12:38.290 回答