1

I am trying to fetch all photos from my device, and show them in a collection:

var allPhotos : PHFetchResult<PHAsset>? = nil  

PHPhotoLibrary.requestAuthorization { status in
    switch status {
    case .authorized:
        let fetchOptions = PHFetchOptions()
        self.allPhotos = PHAsset.fetchAssets(with: .image, options: fetchOptions)
        print("Found \(allPhotos.count) assets")
    case .denied, .restricted:
        print("Not allowed")
    case .notDetermined:
        // Should not see this when requesting
        print("Not determined yet")
    }
}

This code fetches all the photos from the device and as well as from iCloud and then stores them into allPhotos array. But when I am trying to set them using this function in collection view cell, I am only getting photos from the device. The other photos cell is empty. Converting images with this function:

func getUIImage(asset: PHAsset) -> UIImage? {

    var img: UIImage?
    let manager = PHImageManager.default()
    let options = PHImageRequestOptions()
    options.version = .original
    options.isSynchronous = true
    manager.requestImageData(for: asset, options: options) { data, _, _, _ in

        if let data = data {
            img = UIImage(data: data)
        }
    }
    return img
}

And for some images I am getting this error "Failed to load image data for asset " for those empty cells. Can someone explain why it is not fetching iCloud images?

Marcy
  • 4,611
  • 2
  • 34
  • 52
Amalendu Kar
  • 458
  • 1
  • 6
  • 17

2 Answers2

3

Because the following code is a closure.

manager.requestImageData(for: asset, options: options) { data, _, _, _ in

    if let data = data {
        img = UIImage(data: data)
    }
}

And closures execute on background thread and are not inline. Closure execution may take time and might not return data instantaneously.

What you could try is creating a closure callback for image to load.

func getUIImage(asset: PHAsset, complition : @escaping ((_ img:UIImage?,_ error:String?) -> Void)){
let manager = PHImageManager.default()
let options = PHImageRequestOptions()
options.version = .original
options.isSynchronous = true
manager.requestImageData(for: asset, options: options) { data, _, _, _ in

    if let data = data,
    let img = UIImage(data: data){
        complition(img,nil)
    }else{
        complition(nil,"Something went wrong")
        }
    }
}

You can try this. Hope this help.

nishith Singh
  • 2,968
  • 1
  • 15
  • 25
0

Try to add it in requestOptions:

options.isNetworkAccessAllowed = true

It helped me

Sergey Udalov
  • 75
  • 1
  • 7