繁体   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