Reputation: 731
I want to display avatar image in my table view cell by the url string. and it will crash when the phone is not connect to the internet, so I added Reachability swift to it. but now I face another problem, when the user leaving the wifi zone or the internet connection is not stable, the app will freeze, I'm not able to tap anything until I walk back the strong wifi zone. why?
let imageData:NSData = try! NSData(contentsOf: imageUrl)
this code will crash so I try add do & catch but still not working. is it because the app can't connect to the url string and get the data so that the app will be freeze? how to prevent an app crash or freeze due to a slow connection when retrieving a remote photo?
if Reachability.shared.isConnectedToNetwork(){
if let crew = user!["crew"] as? [String:Any], let crewAva = crew["crew_avatar"] as? String {
let imageUrlString = crewAva
let imageUrl:URL = URL(string: imageUrlString)!
DispatchQueue.main.async(execute: {
do{
let imageData:NSData = try NSData(contentsOf: imageUrl)
let image = UIImage(data: imageData as Data)
self.avaImg.image = image
}
catch{
print("error")
}
})
}
}else{
print("Not reachable")
}
Upvotes: 0
Views: 485
Reputation: 731
Solution
func getDataFromUrl(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
completion(data, response, error)
}.resume()
}
func downloadImage(url: URL) {
getDataFromUrl(url: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
DispatchQueue.main.async() {
self.avaImg.image = UIImage(data: data)
}
}
}
override func viewWillAppear(_ animated: Bool) {
if let crew = user!["crew"] as? [String:Any], let crewAva = crew["crew_avatar"] as? String {
let imageUrlString = crewAva
let url = URL(string: imageUrlString)!
downloadImage(url: url)
}
}
Upvotes: 1
Reputation: 285082
From the NSData documentation:
init?(contentsOf url: URL)
Important
Don't use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated. Instead, for non-file URLs, consider using the
dataTask(with:completionHandler:)
method of theNSURLSession
class. See URL Session Programming Guide for details.
Upvotes: 3
Reputation: 1363
Try only updating the UI on the main thread.
if Reachability.shared.isConnectedToNetwork(){
if let crew = user!["crew"] as? [String:Any], let crewAva = crew["crew_avatar"] as? String {
let imageUrlString = crewAva
let imageUrl:URL = URL(string: imageUrlString)!
let imageData:NSData = try NSData(contentsOf: imageUrl)
let image = UIImage(data: imageData as Data)
DispatchQueue.main.async(execute: {
do{
self.avaImg.image = image
}
catch{
print("error")
}
})
}
}else{
print("Not reachable")
}
Upvotes: 0