DispatchQueue不等待异步函数完成

时间:2018-01-23 03:36:04

标签: ios swift xml asynchronous swift4

我正在尝试创建一个使用USPS API来获取数据的简单包跟踪应用。 callRestService 方法成功提取数据及其完成处理程序 serviceCallback (设置 unparsedXml 属性)有效。但是,我调用 callRestService 的方法不会等待它并且它的完成处理程序在继续之前完成,导致我的print(unparsedXml)语句返回nil。

如下所示,我尝试使用DispatchGroup对象和DispatchQueue使函数等待 callRestService 的完成,但无论如何都会继续。如何让函数等待调用完成?

myLogging = logging.getLogger('myOp')
myLogging.setLevel(10)
hdlr = logging.FileHandler(myLogFile)
myLogging.addHandler(hdlr)
myLogging.debug("Message here")

2 个答案:

答案 0 :(得分:2)

您的问题是callRestService将调度异步网络操作,因此系统会立即调用您的group.leave,并触发group.notify

您可以将group.leave放在完成处理程序中,但应避免阻止代码。我建议你将getTrackingInfo构造为带有完成处理程序的异步函数:

public func getTrackingInfo(_ trackingNumber: String, completion:(TrackingInfo?,Error?) -> Void) {
    self.callRestService(requestUrl: self.getRequest(trackingNumber)) { (data, response, error) in
        guard error == nil, let returnData = data else {
            completion(nil,error)
            return
        }

        completion(TrackingInfo(returnData),nil)
    }
}

private func getRequest(_ trackingNumber: String) -> String {
    let APIUsername = "Intentionally Omitted"
    let trackingXmlLink = "http://production.shippingapis.com/ShippingAPI.dll?API=TrackV2&XML=%3CTrackFieldRequest%20USERID=%22" + APIUsername + "%22%3E%20%3CRevision%3E1%3C/Revision%3E%20%3CClientIp%3E127.0.0.1%3C/ClientIp%3E%20%3CSourceId%3EFaiz%20Surani%3C/SourceId%3E%20%3CTrackID%20ID=%22" + trackingNumber + "%22%3E%20%3CDestinationZipCode%3E66666%3C/DestinationZipCode%3E%20%3CMailingDate%3E2010-01-01%3C/MailingDate%3E%20%3C/TrackID%3E%20%3C/TrackFieldRequest%3E"
    return trackingXmlLink
}

public func callRestService(requestUrl:String, completion:(Data? , URLResponse? , Error? ) -> Void) ->Void
{
    var request = URLRequest(url: URL(string: requestUrl)!)
    request.httpMethod = "GET"

    let session = URLSession.shared
    let task = session.dataTask(with: request, completionHandler: completion)

    task.resume()
}

答案 1 :(得分:0)

等待notify中的操作完成 模拟网络请求:

public func networkTask(label: String, cost: UInt32, complete: @escaping ()->()) {
    NSLog("Start network Task task%@",label)
    DispatchQueue.global().async {
        sleep(cost)
        NSLog("End networkTask task%@",label)
        DispatchQueue.main.async {
            complete()
        }
    }
}

let group = DispatchGroup()

group.enter()
networkTask(label: "2", cost: 4) {
  group.leave()
}
group.enter()
networkTask(label: "1", cost: 3) {
  group.leave()
}

group.notify(queue: .main) {
 print("task complete!")
 // ......
}

你可以尝试这个例子。