I am making a Swift
app for iOS and I have an issue on a request I make.
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
. 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.
By "freezes" I mean that I've detected it when I scroll my long 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:
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. But I am not sure. How can I check it? Also, how can I be sure that dataTask is async ?
Here's what the dataTask
code looks like:
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.
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
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.
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
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.