Search code examples
iosswiftuicollectionviewuiimagepickercontrollerelcimagepickercontroller

How to display images that in photo gallery that were just selected?


Goal: The user selects photos from her photo gallery > Tap "Done" > Photos show up.

Problem: The photos don't show up immediately after "Done". They do show up if I open the picker again and tap "Cancel."

This worked fine (photo showed up instantly) when I was using UIImagePickerController, but then I switched to ELCImagePickerController for multiple selection and it no longer works.

Hunches

  • CollectionView that displays all images is not being reloaded? But I tried calling collectionView.reloadData() after the images are selected (on the completionHandler). This did not work.

If helpful, this is my elcImagePickerController function from my ViewController.swift

func elcImagePickerController(picker: ELCImagePickerController!, didFinishPickingMediaWithInfo info: [AnyObject]!) {

    println("inside elcImagePickerController")

    self.dismissViewControllerAnimated(true, completion: nil)

    if (info.count == 0) {
        return
    }

    var pickedImages = NSMutableArray()
    for any in info {
        let dict = any as! NSMutableDictionary
        let image = dict.objectForKey(UIImagePickerControllerOriginalImage) as! UIImage
        pickedImages.addObject(image)
    }

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT

    dispatch_async(dispatch_get_global_queue(priority, 0), {


        PHPhotoLibrary.sharedPhotoLibrary().performChanges(
            {

                for img in pickedImages{

                    // Request creating an asset from the image
                    // create multiple creationRequestForAssetFromImage

                    let createAssetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(img as! UIImage) // add to main gallery

                    // / Request editing the album
                    let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection, assets: self.photosAsset)

                    // Get a placeholder for the new asset and add it to the album editing request
                    let assetPlaceholder = createAssetRequest.placeholderForCreatedAsset

                    albumChangeRequest.addAssets([assetPlaceholder])

                }


            }, completionHandler: {(success, error) in
                NSLog("Adding Image to Library -> %@", (success ? "Success" : "Error"))
                picker.dismissViewControllerAnimated(true, completion: nil)
            }
        )
    })

Solution

  • It took me a while to duplicate your scenario and error, but I managed and I found a solution!

    You were on the right path with calling collectionView.reloadData() in the completionHandler, but it needed a bit more work.


    1)

    In my testing scenario, I've used a PHFetchResult called photosAsset as the main source for the UICollectionView (I'm presuming you have a similar setup).

    You have to update this PHFetchResult to reflect the recent changes, in my case I used the following line:

    self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
    

    2)

    It's correct that you have to reload the view with collectionView.reloadData(), but the code inside of the completionHandler is not run on the main thread/UI thread. So you have to call it like the following:

    dispatch_async(dispatch_get_main_queue(), {self.collectionView?.reloadData()})
    

    Sum up:

    In final, your completionHandler should look something similar to this:

    completionHandler: {(success, error) in
        NSLog("Adding Image to Library -> %@", (success ? "Success" : "Error"))
        self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
        dispatch_async(dispatch_get_main_queue(), {self.collectionView?.reloadData()})
        picker.dismissViewControllerAnimated(true, completion: nil)
    }