简体   繁体   English

URLSession.shared.dataTask 冻结 UI

[英]URLSession.shared.dataTask freezes the UI

I am making a Swift app for iOS and I have an issue on a request I make.我正在为 iOS 制作一个Swift应用程序,但我提出的请求有问题。

This request is made every 3 to 5 seconds and the body is a 5k lines JSON (~130k characters in total) that refreshes a UITableView .此请求每 3 到 5 秒发出一次,主体是 5k 行 JSON(总共约 130k 个字符),用于刷新UITableView The issue is that every time .dataTask is used on this specific request, the app freezes then runs normally after the request has been made.问题是每次.dataTask用于此特定请求时,应用程序都会冻结,然后在发出请求后正常运行。

By "freezes" I mean that I've detected it when I scroll my long UITableView. “冻结”是指在滚动长 UITableView 时检测到它。 Even a small scroll list freezes.即使是一个小的滚动列表也会冻结。

I first suspected the update of the UITableView , but I added a small 'hack' that disables the update of the UITableView when scrolling, like this:我首先怀疑UITableView的更新,但我添加了一个小的“hack”,它在滚动时禁用UITableView的更新,如下所示:

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

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

It doesn't work.它不起作用。

My question is then: I think that dataTask is NOT run in the main thread.我的问题是:我认为 dataTask 不在主线程中运行。 But I am not sure.但我不确定。 How can I check it?我该如何检查? Also, how can I be sure that dataTask is async ?另外,我如何确定 dataTask 是 async ?

Here's what the dataTask code looks like:这是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()

Little note however, it ONLY freezes BEFORE the JSONSerialization, not after, so I guess it is not what it is causing the freeze.然而,请注意,它只在 JSONSerialization 之前冻结,而不是之后,所以我想这不是导致冻结的原因。

URLSession.shared.dataTask runs in background thread, you can move the JSONSerialization and if you are updating the UI move that all in main thread 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
        }
    }
}

Your JSON parsing should be on the background thread, so this parsing operation will not block other things, such as the UI, on the main thread.你的 JSON 解析应该在后台线程上,所以这个解析操作不会阻塞主线程上的其他东西,比如 UI。

Following is an example that uses a completion block that is called on main thread以下是使用在主线程上调用的完成块的示例

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
        }

    }
}

Usage用法

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在URLSession.shared.dataTask之后调用performSegue - Call performSegue after URLSession.shared.dataTask 在URLSession.shared.dataTask中执行performSegueWithIdentifier(with:url) - performSegueWithIdentifier while in URLSession.shared.dataTask(with: url) 当应用程序处于后台时调用URLSession.shared.dataTask - Invoke URLSession.shared.dataTask when the app is background 在URLSession.shared.dataTask期间从异步关闭存储数据 - Storing data from an asynchronous closure during URLSession.shared.dataTask URLSession.shared.dataTask的完成处理程序内部的闭包 - closure inside completion handler of URLSession.shared.dataTask 使用URLSession.shared.dataTask中的JSON和字典进行Swift 3编译器错误 - Swift 3 Compiler Errors with JSON and Dictionaries within URLSession.shared.dataTask 使用 URLSession.shared.dataTask 发出 api 请求 - Making an api request using URLSession.shared.dataTask 获取URL响应状态代码URLSession.shared.dataTask - Get http response status code of URLSession.shared.dataTask iOS UrlSession.shared.dataTask 移除 utf-8 "+" 字符并替换为 " " - iOS UrlSession.shared.dataTask removes utf-8 "+" character and replaces it with " " URLSession.shared.dataTask接收数据的正确方法 - URLSession.shared.dataTask correct way to receive data
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM