I'm trying to get the asset resources for a PHAsset and am having a little trouble. I'm able to fetch the PHAsset with no problems, yet the resources for the asset is always empty. This is not happening with every photo, but one in particular has been giving me troubles. Curious if there's something I'm missing and this is expected behaviour in certain contexts.
import UIKit
import Photos
import PhotosUI
class ViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
requestPhotoLibraryAuthorization() { success in
let identifier = "E218D471-E616-4E39-99C3-624D13D9B661/L0/001"
let assets = self.fetchPHAssets(identifiers: [identifier])
guard assets.count > 0 else { return }
let imageOptions = PHImageRequestOptions()
imageOptions.deliveryMode = .highQualityFormat
imageOptions.isNetworkAccessAllowed = true
PHImageManager.default().requestImage(for: assets[0], targetSize: PHImageManagerMaximumSize, contentMode: .default, options: imageOptions) { (image, info) in
print(String(describing: info)) // never called
}
self.saveAssetToDisk(asset: assets[0]) { image in
guard let image = image else { return }
self.imageView.image = image
}
}
}
func fetchPHAssets(identifiers: [String]) -> [PHAsset] {
let options = PHFetchOptions()
options.includeAllBurstAssets = false
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
options.fetchLimit = identifiers.count
options.includeAssetSourceTypes = [.typeCloudShared, .typeiTunesSynced, .typeUserLibrary]
let assetResult = PHAsset.fetchAssets(withLocalIdentifiers: identifiers, options: options)
var assetArray:[PHAsset] = []
for i in 0..<assetResult.count {
let asset = assetResult[i]
assetArray.append(asset)
}
return assetArray
}
func saveAssetToDisk(asset: PHAsset, onComplete: @escaping (UIImage?)->()) {
let resources = PHAssetResource.assetResources(for: asset)
guard resources.count > 0 else { return }
let resource = resources[0]
let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentUrl = urls[0]
let resourceUrl = documentUrl.appendingPathComponent(resource.originalFilename, isDirectory: false)
// write image
let options = PHAssetResourceRequestOptions()
options.isNetworkAccessAllowed = true
if !FileManager.default.fileExists(atPath: resourceUrl.path) {
PHAssetResourceManager.default().writeData(for: resource, toFile: resourceUrl, options: options) { error in
if error == nil {
guard let image = UIImage(contentsOfFile: resourceUrl.path) else { return }
onComplete(image)
}
}
} else {
onComplete(UIImage(contentsOfFile: resourceUrl.path))
}
}
let requestPhotoLibraryKey = "hasRequestedPhotoAccess"
func requestPhotoLibraryAuthorization(onComplete: @escaping (Bool) -> ()) {
let status = PHPhotoLibrary.authorizationStatus()
if status == .notDetermined {
PHPhotoLibrary.requestAuthorization { status in
if status == PHAuthorizationStatus.authorized {
UserDefaults.standard.set(true, forKey: self.requestPhotoLibraryKey)
onComplete(true)
}
}
} else if status == .authorized {
UserDefaults.standard.set(true, forKey: requestPhotoLibraryKey)
onComplete(true)
} else if status == .denied {
onComplete(false)
}
}
}