RequestImage's result handler called twice

751 Views Asked by At

I have an array of image assets. I have to turn those assets into images, add them to an array and upload them to Firebase Database. I have 2 issues with this.

Issue 1:

In a custom UICollectionViewCell I display all the images that the user has selected, I see 4 images in the cell, when I've selected 4 images from the Photos (I'm using a custom framework). Now, when I call requestImage method, I get double the amount of images in the array that's supposed to convert each asset from the asset array and store it into a UIImage array called assetsTurnedIntoImages. I read more about it and it's related to the PHImageRequestOptions and if its isSynchronous property returns true or false, that or if PHImageRequestOptions is nil. Now, obviously I didn't get something because my code still doesn't work.

Issue 2:

As you can see from the code below, the targetSize gives me a somewhat thumbnail image size. When I upload the image to the storage, I don't need a thumbnail, I need it's original size. If I set it to PHImageManagerMaximumSize I get an error:

"Connection to assetsd was interrupted or assetsd died”

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoPostCVCell", for: indexPath) as! PhotoPostCVCell
    if let takenImage = cameraPhotoUIImage
    {
        cell.cellImage.image = takenImage
    }
    if assets.count > 0
    {
        let asset = assets[indexPath.row]
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = true  // synchronous works better when grabbing all images
        requestOptions.deliveryMode = .opportunistic
        imageManager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFill, options: requestOptions)
        { (image, _) in
            DispatchQueue.main.async {
                print("WE ARE IN")
                cell.cellImage.image = image!
                self.assetsTurnedIntoImages.append(image!)
            }
        }
    }
    return cell
}
2

There are 2 best solutions below

0
On

To avoid completion handler's twice calling, just add an option in this request to make it synchronous

 let options = PHImageRequestOptions()
 options.isSynchronous = true
 let asset: PHAsset = self.photoAsset?[indexPath.item] as! PHAsset

    PHImageManager.default().requestImage(for: asset, targetSize: CGSize(width: 1200, height: 1200), contentMode: .aspectFit, options: options, resultHandler: {(result, info) in
        if result != nil {

           //do your work here


        }
    })

To avoid crash on loading image you should compress the image or reduce its size for further work

0
On

Change the option could solve the problem:

options.deliveryMode = .highQualityFormat

I found that solution in the source code:

@available(iOS 8, iOS 8, *)
public enum PHImageRequestOptionsDeliveryMode : Int {

    
    @available(iOS 8, *)
    case opportunistic = 0 // client may get several image results when the call is asynchronous or will get one result when the call is synchronous

    @available(iOS 8, *)
    case highQualityFormat = 1 // client will get one result only and it will be as asked or better than asked

    @available(iOS 8, *)
    case fastFormat = 2 // client will get one result only and it may be degraded
}