在 Xcode 9 / Swift 4 Google APIs Client Library for Objective-C for REST: threading notification not working

In Xcode 9 / Swift 4 Google APIs Client Library for Objective-C for REST: threading notification not working

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

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 **************** *********** *************************** 通知主线程 ********************* *******************

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

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

此外,回调队列可能不是为您添加自己的任务而设计的。这是一个库将用于其回调的队列(完成块 and/or 委托方法的队列将是 运行)。只需调用 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
}