I have a collection view that is being populated with images created from parsed data. It is being populated and updated by using an NSFetchedResultsController as the data source. The code is in Swift 4, so to do so I am using the data source methods for the collection view along with the delegate methods for the NSFetchedResultsControllerDelegate as shown here:
func collectionView (_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if let count = fetchedResultsController.sections?[0].numberOfObjects {
return count
}else {
return 0
}
}
func collectionView (_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("Setting cell with photo")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! CollectionViewCell
let photoForCell = fetchedResultsController.object(at: indexPath)
cell.cellImage.image = UIImage(data: photoForCell.imageData!)
print(photoForCell.imageData!)
return cell
}
I am trying to calculate how many images were pulled in the parsed data and use this information to temporarily populate that many cells in the collection view with the same placeholder image in all of them. Then, once the images have all been downloaded and saved the NSFetchedResultsController will trigger the data source methods to refresh and populate the collection view with the new photos instead of the placeholder photos.
I have not been able to find any videos or posts that show how to do so. I tried creating a variable that holds the count of objects in the parsed data. That variable is then used in an if statement in the (:numberOfItemsInSection:) and (:cellForItemAt:) to determine whether it should populate the collection from saved photos or using the temporary photos like this:
func collectionView (_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if self.placeHolderCount != nil {
return placeHolderCount
}
if let count = fetchedResultsController.sections?[0].numberOfObjects {
return count
}else {
return 0
}
}
func collectionView (_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
print("Setting cell with photo")
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoCell", for: indexPath) as! CollectionViewCell
let photoForCell = fetchedResultsController.object(at: indexPath)
if self.placeHolderCount != nil {
cell.cellImage.image = #imageLiteral(resourceName: "VirtualTourist_5112")
return cell
}
cell.cellImage.image = UIImage(data: photoForCell.imageData!)
print(photoForCell.imageData!)
return cell
}
Unfortunately, that causes the app to crash with an error saying "NSInvalidArgumentException reason: 'no object at index 0 in section at index 0"
During my troubleshooting, I found that this crash happens at the point when the view context is saved after downloading all the images. Everything in the application works perfectly including loading the downloaded images until I add the changes to the delegate methods. Does anyone know if I am on the right track? Should I be going about it in a completely different way? I have seen external libraries around that will accomplish this, but I cannot use any external libraries or frameworks for this particular application.