Igor Voitenko Igor Voitenko - 15 days ago 5
iOS Question

Using UIImageView+AFNetworking, images doesn't appear until scrolling

I'm using

UIImageView+AFNetworking
to load images in table cell, but
images downloaded from server aren't shown in cell until scroll down and up again. I thought that I needed to reload data in
tableView
, but I don't know where to put said reload code.

Here's the code:

@IBOutlet weak var refresherTool: UIRefreshControl!



override func viewDidLoad() {
super.viewDidLoad()


let _ = dataRefresher.sharedInstance.refreshVideos(fromUrl: "https://api.vid.me/videos/featured", withLimit: "100", withOffset: "0", completion: {
featuredVideos in dataRefresher.sharedInstance.featuretVideos = featuredVideos
DispatchQueue.main.async {
self.tableView.reloadData()
}
})

}

@IBAction func refreshBtn(_ sender: UIRefreshControl) {
let _ = dataRefresher.sharedInstance.refreshVideos(fromUrl: "https://api.vid.me/videos/featured", withLimit: "100", withOffset: "0", completion: {
featuredVideos in dataRefresher.sharedInstance.featuretVideos = featuredVideos
self.refresherTool.endRefreshing()
DispatchQueue.main.async{
self.tableView.reloadData()
}
})
refresherTool.endRefreshing()
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if dataRefresher.sharedInstance.featuretVideos == nil {
return 0
}
return 100
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "featuredCell", for: indexPath)
// if dataRefresher.sharedInstance.featuretVideos == nil { return cell}
let newImage = UIImageView()
newImage.setImageWithUrl(URL.init(string: dataRefresher.sharedInstance.getVideosThumbnailUrls(fromVideos: dataRefresher.sharedInstance.featuretVideos)[indexPath.row])!, placeHolderImage: #imageLiteral(resourceName: "first"))
// newImage.setImageWithUrl(URL.init(string: urls[indexPath.row])!)
cell.imageView?.image = newImage.image

cell.textLabel?.text = dataRefresher.sharedInstance.getVideosTitels(fromVideos: dataRefresher.sharedInstance.featuretVideos)[indexPath.row]

print(indexPath.row)
print(newImage.image!)
return cell
}

Answer

The setImageWithUrl method is asynchronous, meaning that if the referenced image is not in the local cache yet, it will only be downloaded some time in the future.

However, your code tries to get the image out right away:

let newImage = UIImageView()
newImage.setImageWithUrl(..., placeHolderImage: ...)
cell.imageView?.image = newImage.image <-- synch call, image is nil here at first!

Fortunately, there's no need to reload the table view or do any other arcane tricks; just stop doing unnecessary things.

Remove the temporary UIImageView and load the image into the cell's UIImageView directly.

The above code becomes:

cell.imageView?.setImageWithUrl(..., placeHolderImage: ...)