我正在为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是异步的?
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之前冻结,而不是之后冻结,因此我想这不是导致冻结的原因。
答案 0 :(得分:1)
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
}