[英]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.