Search code examples
swiftphpickerviewcontroller

PHPickerViewController: How to deselect the previous selected image when reopen the image picker


I create an app with PHImagePicker support. It works and I could select multiple photos from photo library and import them into this app. But when I reopen this pickerController, the previous selected images are there with blue marks. I must to unselect them first to select some new images.

My question is how could I clear the previous selected images state each time I open the imagePickerController?

PHImagePicker

import UIKit
import PhotosUI

public protocol PHImagePickerDelegate: AnyObject {
    func didSelect(images: [UIImage]?)
}

class PHImagePicker: NSObject {
    
    private let pickerController: PHPickerViewController
    private weak var presentationController: UIViewController?
    private weak var delegate: PHImagePickerDelegate?
    private var images = [UIImage]()
    
    public init(presentationController: UIViewController, delegate: PHImagePickerDelegate) {
        var config = PHPickerConfiguration()
        config.selectionLimit = 3
        // only show images
        config.filter = PHPickerFilter.images
        
        self.pickerController = PHPickerViewController(configuration: config)
        
        super.init()
        
        self.presentationController = presentationController
        self.delegate = delegate
        self.pickerController.delegate = self
    }
    
    private func pickerController(_ controller: PHPickerViewController, didSelect images: [UIImage]?) {
        controller.dismiss(animated: true, completion: nil)
        
        self.delegate?.didSelect(images: images)
    }
    
    public func present(from sourceView: UIView) {
        self.presentationController?.present(pickerController, animated: true)
    }
}

extension PHImagePicker: PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        // clear images array
        self.images = []
        
        // dismiss the picker
        picker.dismiss(animated: true, completion: nil)
        print(picker)
        print(results)
        
        for result in results {
            print("💄assetIdentifier", result.assetIdentifier ?? "")
            print("💄itemProvider", result.itemProvider)
            
            result.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] object, error in
                if let error = error {
                    print("ERROR: 💄", error)
                    return
                }
                print(object as Any)
                
                if let image = object as? UIImage {
                    self?.images.append(image)
                    
                    if self?.images != nil && self?.images.count == results.count {
                        DispatchQueue.main.async {
                            self?.pickerController(picker, didSelect: self?.images)
                        }
                    }
                }
            }
        }
    }
}

ViewController

    @objc func importButtonTapped(_ sender: UIButton) {
        // ... omitted code
        self.imagePicker.present(from: sender)
    }

Solution

  • You are reusing the same instance of PHImagePicker every time:

    self.imagePicker.present(from: sender)
    

    That means you are using the same PHPickerController, which has the same set of selected photos. An easy way to fix is to create a new PHImagePicker every time:

    PHImagePicker(presentationController: self, delegate: self).present(from: sender)
    

    You can also rewrite present so that it recreates the PHPickerController.