首页 文章

DispatchQueue不等待异步函数完成

提问于
浏览
1

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

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

var unparsedXml:String?

public func getTrackingInfo(_ trackingNumber: String) -> TrackingInfo {
    let group = DispatchGroup()
    group.enter()
    DispatchQueue.global(qos: DispatchQoS.default.qosClass).async {
        self.callRestService(requestUrl: self.getRequest(trackingNumber))
        group.leave()
    }
    group.wait()
    print(unparsedXml)
    return TrackingInfo()
}

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) ->Void
{
    var request = URLRequest(url: URL(string: requestUrl)!)
    request.httpMethod = "GET"

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

    task.resume()
}

private func serviceCallback(data:Data? , response:URLResponse? , error:Error? ) -> Void
{
    unparsedXml = String(data: data!, encoding: .utf8)
    //print(unparsedXml) Works correctly when uncommented
}

2 回答

  • 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!")
     // ......
    }
    

    你可以尝试这个例子 .

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

相关问题