I have a DetailViewController that is segued to when you click on a table view cell , the detail view shows a label , rating and a collectionView , the UICollectionView setup like this , ideally it should show two images that are downloaded and put into the image array
class DetailViewController: UIViewController , UICollectionViewDelegate , UICollectionViewDataSource{
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var LabelView: UILabel!
@IBOutlet weak var RatingsView: CosmosView!
var mv : Result?
var imgArr = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
LabelView.text = mv?.title
RatingsView.rating = Double((mv!.vote_average / 2))
let uri = "https://image.tmdb.org/t/p/w92" + mv!.poster_path
downloadImage(with : uri){image in
guard let image = image else { return}
self.imgArr.append(image)
}
let bUri = "https://image.tmdb.org/t/p/w92" + mv!.backdrop_path
downloadImage(with : bUri){image in
guard let image = image else { return}
self.imgArr.append(image)
dump(self.imgArr)
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imgArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
cell.imgImage.image = imgArr[indexPath.row]
return cell
}
func downloadImage(with urlString : String , imageCompletionHandler: @escaping (UIImage?) -> Void){
guard let url = URL.init(string: urlString) else {
return imageCompletionHandler(nil)
}
let resource = ImageResource(downloadURL: url)
KingfisherManager.shared.retrieveImage(with: resource, options: nil, progressBlock: nil) { result in
switch result {
case .success(let value):
imageCompletionHandler(value.image)
case .failure:
imageCompletionHandler(nil)
}
}
}
}
Here is what it looks like in storyboard , I have the proper classes and reuseIdentifiers assigned
But I can’t see any images for some reason
I have no clue why it won’t show the images , it did before I changed the layout to add a master stack view , but I can’t figure out why a minor layout change would affect , I still think i’m doing something wrong in the code. I tried adding .reloadData() and other troubleshooting but it didn’t work.
The images are downloading as seen in the output dump which prints when you segue to the detail view.
Please help me out.
Thanks in advance
2
Answers
You should always update anything on UI on the main thread. Please add your returned image inside DispatchQueue.main.async {}
Almost certainly — the problem is that the collection view loads before the images are downloaded.
In
viewDidLoad()
you start an async process of downloading two images. That will take "some time" — it might take 1/4 second, 1/2 second… or it may be very quick (if they are small images) and only take 1/10th of a second.However,
numberOfItemsInSection
is probably being called at 1/100th of a second – well before the images have been downloaded.Change that to:
and you’ll likely see
number of images: 0
as the output.In your completion block(s), you need to add:
Note also… those two images won’t necessarily download consecutively. If you need them in that order, you will either want to:
imgArr
and then replace them in the desired orderIn any case, you’ll still need to call
.reloadData()
after the images have downloaded.