0

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.

Sudhanshu Vohra
  • 1,345
  • 2
  • 14
  • 21
John Nolan
  • 65
  • 9
  • 1
    For that you can't need to do anything just use this for Display placeholder image before Download and Update actual image https://stackoverflow.com/a/51746517/10150796 – Nikunj Kumbhani Aug 24 '18 at 05:07
  • @NikunjKumbhani I am not sure I understand how to apply that to the code shown above. The placeholder image can be referenced by an image literal. The images that are coming from url are being downloaded in the http request method. Both are loaded into the collection view at different times. How would I implement your suggestion in the code above? – John Nolan Aug 25 '18 at 00:42

0 Answers0