Search code examples
swiftuicollectionviewuiimagepickercontrollerphpickerviewcontroller

Replacing default images in a collection view with user selected photos- swift


So I have a collection view that populates three default images on each cell. The user can select images through the new PHPicker, what I want to accomplish is

  1. to replace default images with selected photos, so the first selected image should replace the camera cell and so on ... (see images through links at the bottom)
  2. to display the default images in case user deletes the selected images

currently when I send a new photo to the imgArray it gets displayed in a new cell before the camera cell, as I'm using insert method like so: imgArray.insert(image, at: 0).

My code:

  var imgArray = [UIImage(systemName: "camera"), UIImage(systemName: "photo"), UIImage(systemName: "photo")]

   func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "1", for: indexPath) as! CustomCell
    cell.imageView.image = imgArray[indexPath.row]
    cell.imageView.tintColor = .gray
    cell.imageView.layer.cornerRadius = 4
    return cell
}

 func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    dismiss(animated: true, completion: nil)
    
    for item in results {
        
        item.itemProvider.loadObject(ofClass: UIImage.self) { image, error in

            if let image = image as? UIImage {
                DispatchQueue.main.async {
                    self.imgArray.insert(image, at: 0)
                    self.collectionView.reloadData()
                }
            }
        }
    }
}

I have tried to remove the first item of the array, and then insert new photo like this:

                    self.imgArray.removeFirst(1)
                    self.imgArray.insert(image, at: 0)
                    self.collectionView.reloadData()

but this would work just one time as the code itself says, after that all replacement takes place just in the first cell. So how can I get to other cells after first replacement? Any other approach that gives the same result will help me alot. Thanks in advance guys!

before selection

after selecting three images


Solution

  • One way to do this is to keep two image arrays, defaultImages of type [UIImage] and inputImages of type [UIImage?]. The defaultImages will hold your camera and photo images, and inputImages will hold images selected by the user. Initialize the images as:

    defaultImages = [UIImage(systemName: "camera"), UIImage(systemName: "photo"), UIImage(systemName: "photo")]
    inputImages: [UIImage?] = [nil, nil, nil]
    

    To select the correct photo for index index use:

    image = inputImages[index] ?? defaultImages[index]
    

    To add a user-input image at index index use:

    image: UIImage = ...  // Get the image.
    inputImages[index] = image
    

    And to delete a user-input image at index index use:

    inputImages[index] = nil