Reputation: 2059
Trying to load images in tableView
asynchronously in (Xcode 9 and Swift 4) and seems I have a correct way but my code stops working if I scroll my tableView
fast. So basically I had found nil error.
Here is my code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let feed = feeds[indexPath.row]
cell.titleLabel.text = feed.title
cell.pubDateLabel.text = feed.date
cell.thumbnailImageView.image = nil
if let image = cache.object(forKey: indexPath.row as AnyObject) as? UIImage {
cell.thumbnailImageView?.image = image
} else {
let imageStringURL = feed.imageUrl
guard let url = URL(string: imageStringURL) else { fatalError("there is no correct url") }
URLSession.shared.downloadTask(with: url, completionHandler: { (url, response, error) in
if let data = try? Data(contentsOf: url!) {
DispatchQueue.main.async(execute: {
guard let image = UIImage(data: data) else { fatalError("can't create image") }
let updateCell = tableView.cellForRow(at: indexPath) as! CustomTableViewCell // fast scroll issue line
updateCell.thumbnailImageView.image = image
self.cache.setObject(image, forKey: indexPath.row as AnyObject)
})
}
}).resume()
}
return cell
}
I have issue on the line:
let updateCell = tableView.cellForRow(at: indexPath) as! CustomTableViewCell
If I scroll down slowly everything works just fine and no mistakes appear.
Does anyone know where I've made a mistake?
Upvotes: 0
Views: 310
Reputation: 3404
This may happens if cell you are trying to get using tableView.cellForRow(at:)
is not visible currently.
To avoid crash you can use optionals as:
let updateCell = tableView.cellForRow(at: indexPath) as? CustomTableViewCell // fast scroll issue line
updateCell?.thumbnailImageView.image = image
Keep everything as it is, I hope it should work without any errors.
Upvotes: 3
Reputation: 846
You can consider one of popular UIImage extension libs, like I said in comment for example AlamofireImage and set thumbnail with the placeholder, as soon as image will be ready it will be replaced automatically.
One more thing I change no need to have updateCell I removed it.
Please add placeholder image and test it should work, sorry I didn't fully check syntax.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTableViewCell
let feed = feeds[indexPath.row]
if let image = cache.object(forKey: indexPath.row as AnyObject) as? UIImage {
cell.thumbnailImageView?.image = image
} else {
let imageStringURL = feed.imageUrl
guard let url = URL(string: imageStringURL) else { fatalError("there is no correct url") }
cell.thumbnailImageView.af_setImage(withURL : url, placeholderImage: <your_placeholderImage>)
return cell
}
Upvotes: 0