簡體   English   中英

URLSession.shared.dataTask 凍結 UI

[英]URLSession.shared.dataTask freezes the UI

我正在為 iOS 制作一個Swift應用程序,但我提出的請求有問題。

此請求每 3 到 5 秒發出一次,主體是 5k 行 JSON(總共約 130k 個字符),用於刷新UITableView 問題是每次.dataTask用於此特定請求時,應用程序都會凍結,然后在發出請求后正常運行。

“凍結”是指在滾動長 UITableView 時檢測到它。 即使是一個小的滾動列表也會凍結。

我首先懷疑UITableView的更新,但我添加了一個小的“hack”,它在滾動時禁用UITableView的更新,如下所示:

    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        print("started scrolling")
        self.currentlyScrolling = true
    }

    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        print("stopped scrolling")
        self.currentlyScrolling = false
    }

它不起作用。

我的問題是:我認為 dataTask 不在主線程中運行。 但我不確定。 我該如何檢查? 另外,我如何確定 dataTask 是 async ?

這是dataTask代碼的樣子:

let task = URLSession.shared.dataTask(with: req) { data, response, err in
        guard let data = data, err == nil else {
            // error
            return
        }

        if let resp = try? JSONSerialization.jsonObject(with: data) {
            // success
        }
    }

    task.resume()

然而,請注意,它只在 JSONSerialization 之前凍結,而不是之后,所以我想這不是導致凍結的原因。

URLSession.shared.dataTask在后台線程中運行,您可以移動JSONSerialization ,如果您正在更新 UI 移動所有在主線程中

let task = URLSession.shared.dataTask(with: req) { data, response, err in {

    // HERE YOU ARE IN BACKGROUND THREAD, see print result in debug area

    print("You are on \(Thread.isMainThread ? "MAIN" : "BACKGROUND") thread.")

    guard let data = data, err == nil else { return }

    if let resp = try? JSONSerialization.jsonObject(with: data) {
        DispatchQueue.main.async {
            print("Now moved to \(Thread.isMainThread ? "MAIN" : "BACKGROUND") thread")

            // success, ANY UI UPDATES MUST BE MADE HERE
        }
    }
}

你的 JSON 解析應該在后台線程上,所以這個解析操作不會阻塞主線程上的其他東西,比如 UI。

以下是使用在主線程上調用的完成塊的示例

func myApiTask(with request: URLRequest, completion:@escaping (_ data: Any?) -> Void) {
    let task = URLSession.shared.dataTask(with: request) { data, response, error in

        var resp: Any?
        defer {
            DispatchQueue.main.async{ completion(resp) }
        }

        if data == nil && error == nil {
            resp = try? JSONSerialization.jsonObject(with: data!)
        } else {
            // error handling
        }

    }
}

用法

myApiTask(with: req) { data in
    // you are on main thread
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM