在DispatchQueue.global(qos:.userInitiated).async完成之前调用DispatchQueue.main.async

时间:2018-04-05 03:25:06

标签: ios swift multithreading

我在互联网上搜索了所有线程swift 4,这就像我在下面的代码中运行它一样:

var ads = [Ads]()

    func viewDidLoad() {
        DispatchQueue.global(qos: .userInteractive).async {
            requestAds()//set self.ads from API and need 1-5 second to response

            DispatchQueue.main.async {
                self.ads = getAds()
                print(self.ads.count) //always 0 because this code run before request completed
                self.adsTableView.reloadData()
            }
        }
    }

但是所有的代码都像不使用DispatchQueue一样运行:

requestAds()
self.ads = getPromos()
print(self.ads.count)
self.promoTableView.reloadData()

这是requestAds():

func requestAds() {
        let adsProvider = AdsDataService.instance.adsProvider
            adsProvider.request(.allAds, completion: { (result) in
                switch result {
                case .success(let response):
                    print(response.debugDescription)
                    guard let reqAds = try? JSONDecoder().decode([Ads].self, from: response.data) as [Ads] else {
                        print("Can't decode json")
                        return}
                    self.ads = reqAds
                case .failure(let error):
                    print(error)
                }
            })
    }

和我的getAds():

func getAds() → [Ads] {
        requestAds()
        return ads
    }

当我使用服务器运行代码中的代码DispatchQueue.main.asyncAfter(deadline: .now() + 6.0, execute: code)使用延迟6秒(因为我无法确定服务器时间响应)时这是有效的,但我认为这是实现此错误的方法。

任何人都有同样的问题吗?或者可以帮我吗?谢谢!

1 个答案:

答案 0 :(得分:0)

您无法预先设置响应时间,因为它未确定。服务器响应的时间取决于许多情况,如互联网连接,服务器容量等。

从服务器下载数据时,您必须等到请求完成。我建议您阅读有关使用API​​ here的更多信息。

尝试这样的事情:

var ads = [Ads]()

func viewDidLoad() {
    requestAds { [weak self] (ads) in
        self?.ads = ads
        DispatchQueue.main.async {
            self?.adsTableView.reloadData()
        }
    }
}

func requestAds(completion: ([Ads], Error?) -> ()) {
    let adsProvider = AdsDataService.instance.adsProvider
    adsProvider.request(.allAds) { (result) in
        switch result {
        case .success(let response):
            guard let reqAds = try? JSONDecoder().decode([Ads].self, from: response.data) as [Ads] else {
                completion([], nil)
                return
            }
            completion(reqAds, nil)
        case .failure(let error):
            completion([], error)
        }
    }
}

这里的要点是:

  • 请求必须有退出点
  • 更新UI始终必须在主线程中

我们使用线程同时执行多个操作,而不是等待服务器的响应。您可以从Apple GuideGCD intro post了解线索。