Search code examples
iosswiftphpickerviewcontrollerphotosui

iOS 14: PHPickerViewController is there any way to load all assets at the same time PHPickerResult


Currently, I am trying to dive into PHPickerViewController for select multiple image at same time from Photos. so I want to array of image that selected by user, i tried it too many way but no luck. This is my code please tell me there is an best practice for to do it?

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true, completion: nil)
        var images: [UIImage?] = []
        var totalConversionsCompleted = 0
        for (index,result) in results.enumerated() {
            result.itemProvider.loadObject(ofClass: UIImage.self, completionHandler: { (object, error) in
                let image = object as? UIImage
                images.append(image)
                totalConversionsCompleted += 1
                if totalConversionsCompleted == index {
                    print("completion happen \(images)")
                }
            })
        }
    }

Solution

  • I got it working using single DispatchGroup. This is my delegate method implementation:

    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true) // dismiss a picker
        
        let imageItems = results
            .map { $0.itemProvider }
            .filter { $0.canLoadObject(ofClass: UIImage.self) } // filter for possible UIImages
        
        let dispatchGroup = DispatchGroup()
        var images = [UIImage]()
        
        for imageItem in imageItems {
            dispatchGroup.enter() // signal IN
            
            imageItem.loadObject(ofClass: UIImage.self) { image, _ in
                if let image = image as? UIImage {
                    images.append(image)
                }
                dispatchGroup.leave() // signal OUT
            }
        }
        
        // This is called at the end; after all signals are matched (IN/OUT)
        dispatchGroup.notify(queue: .main) {
            print(images)
            // DO whatever you want with `images` array
        }
    }