Dani
Dani

Reputation: 3637

Numbers Of Items in UICollectionView issue

I have a UICollectionView with 1 section only, but it has 2 custom UICollectionViewCell. The main purpose of the cells is to display media (mostly images) that the user has selected on previous UIViewController. Cell 1 is always shown first and it's not changing. It's used for the user to be able to click on it and add more photos in the UICollectionView. Cell 2 on the other is used to display all of the images. Now, the number of the cells would vary based on:

1) The user used the camera and took a photo (then the

2) The user selected multiple PHAssets that were converted into UIImage and displayed in the cell.

In both cases, cell 1 is being displayed. The problem comes with displaying the number of items in the array that contains all the images. If I have selected 4 assets from the Camera roll, I ALWAYS get 3 images (not 4!). And I assume this is due to the fact that I return assets.count in the numberOfItemsInSection method while setting up the UICollectionView. This of course cuts off the last image of the array since cell 1 uses it's space.

I tried return assets.count + 1 but it crashes when the PHAssets are turned into images and it says

Index out of range

I don't know what I'm doing wrong. Here's the code:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        // Add More Photos Cell
        if indexPath.item == 0
        {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddMorePhotosCell", for: indexPath) as! AddMorePhotosCell
            return cell
        }
        // Photos Cell
        else
        {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoPostCVCell", for: indexPath) as! PhotoPostCVCell
            if let takenImage = cameraPhotoUIImage
            {
                cell.cellImage.image = takenImage
            }
            if assets.count > 0
            {
                let asset = assets[indexPath.row]

                var imageRequestOptions: PHImageRequestOptions
                {
                    let options = PHImageRequestOptions()
                    options.version = .current
                    options.resizeMode = .exact
                    options.deliveryMode = .fastFormat
                    options.isSynchronous = true
                    return options
                }
                // TODO: Fix the size of the images. Right now it's 500x500
                let targetSize = CGSize(width: 500, height: 500)
                imageManager.requestImage(for: asset, targetSize: targetSize, contentMode: .aspectFill, options: imageRequestOptions)
                { (image, info) in
                    if image != nil
                    {
                        print(image!.size)
                        cell.cellImage.image = image
                        self.assetsTurnedIntoImages[indexPath.row] = image!
                        print("Assets turned into images is: ", self.assetsTurnedIntoImages.count)
                        // TODO: Fix Delete button - Right now it doesn't delete the right image from the cell, but the last one!

                        cell.deleteButton?.tag = indexPath.row
                        cell.deleteButton?.addTarget(self, action: #selector(self.deleteImage(sender:)), for: UIControlEvents.touchUpInside)
                    }
                }
            }
            return cell
        }
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
    {
        if assets.count > 0
        {
            return assets.count + 1
        }
        else
        {
            return 2
        }
    }

Upvotes: 0

Views: 1945

Answers (2)

Dani
Dani

Reputation: 3637

I figured it out, but credit goes to @DonMag because he was right. First of all, I was right about the fact that numberOfItemsInSection needs to be the array.count + 1 because we need 1 more item for the Cell1. So, we have:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    if assets.count > 0
    {
        return assets.count + 1
    }
    else
    {
        return 2
    }
}

But also, the important part was let asset = assets[indexPath.item - 1] and also the place where we turn each PHAsset into an image, which is this line:

self.assetsTurnedIntoImages[indexPath.item - 1] = image!

Upvotes: 0

DonMag
DonMag

Reputation: 77462

You need to adjust the array index. Think of it this way:

  • array of 4 images = [A, B, C, D]
  • First Cell is not in the array
  • Total Number of Items? 5
  • CollectionView says "Give me item 1" - you return FirstCell
  • CollectionView says "Give me item 2" - you need to return the 1st element of the array, NOT the 2nd element

so...

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        // Add More Photos Cell
        if indexPath.item == 0
        {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddMorePhotosCell", for: indexPath) as! AddMorePhotosCell
            return cell
        }
        // Photos Cell
        else
        {
            // offset the index by -1 for the FirstCell
            let asset = assets[indexPath.item - 1]

            // the rest of the stuff
        }

     }

Hope that is clear...

Upvotes: 1

Related Questions