Search code examples
iosswiftuicollectionviewframeworksuiimagepickercontroller

How do I convert assets to UIImages to display photos within a UICollectionView?


I've been using the DKImagePickerController library to select and display multiple images from the iPhone photo library, and my goal is to display the selected images within a UICollectionView. The assets are first passed over from one view controller to another (the 'Preview' view controller) as an array of type 'DKAsset' which is what the library requires I believe. The Preview VC is where I'm attempting to display the photos within a Collection View.

To this do, I've tried to convert the DKAssets into UIImages before storing them in an empty array of type UIImage. Perhaps my approach here is flawed, but I've not been able to convert the assets to UIImages (i.e. the 'print(images)' statement in viewDidLoad returns an empty array), although the end-goal is merely to display photos in the Collection View.

Could anyone assist me in figuring out how to achieve this? My code is below. Many thanks.

class PreviewImageViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

@IBOutlet var collectionView: UICollectionView!

var assets: [DKAsset] = []
var images: [UIImage] = []

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView.dataSource = self
    collectionView.delegate = self
    print(assets)
    
    convertAssetsToImages()
    //the print statement below return an empty array, so something is not working
    print(images)
}

//the function below is how I've been attempting to convert DKAssets to UIImages, in order to store them in the empty UIImage array.
func convertAssetsToImages() {
    for asset in assets {
        asset.fetchOriginalImage(completeBlock: {(image, info) in
            
            self.images.append(image!)

        })
    }
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return assets.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
    //the 'previewImage' below is an IBOUtlet of a UIImageView in another Swift file called 'CollectionViewCell'
    cell.previewImage.image = images[indexPath.item]
    return cell
} 
}

Solution

  • I think print(images) is firing before the block is complete which is why it is still empty. You can test printing to the logs in the block of convertAssetsToImages() to see what fires when. A possible solution would be to remove the UIImage array to have one array (easier to manage) and convert the asset to a UIImage on the collectionView cellForRow

    Code would look like this:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
        
        // Get asset at indexPath
        let asset = assets[indexPath.item]
        asset.fetchOriginalImage(completeBlock: {(image, info) in
            
            if let image = image {
                cell.previewImage.image = image
            }
        })
        
        
        return cell
    }
    

    And don't forget to call collectionView.reloadData() in viewDidLoad

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.reloadData()
        print(assets)
    }
    

    You can remove the UIImage array and anything that references it

    Hope this helps - let me know if it doesn't work and I'll run the code and help you find a solution