diff --git a/Source/AssetManager.swift b/Source/AssetManager.swift index edb6e52d..3184b29e 100644 --- a/Source/AssetManager.swift +++ b/Source/AssetManager.swift @@ -24,27 +24,84 @@ open class AssetManager { return UIImage(named: name, in: bundle, compatibleWith: traitCollection) ?? UIImage() } + + // Fetch assets from a named album + private static func fetchFromAlbum(withConfiguration configuration: ImagePickerConfiguration, + _ completion: @escaping (_ assets: [PHAsset]) -> Void) { + + if configuration.albumName == nil { + fetch(withConfiguration: configuration, + assetCollection: nil) { albumAssets in + completion(albumAssets) + } + return + } + + var assets = [PHAsset]() + + // Title is supposed to be supported as a predicate - but isn't + // https://www.google.com/search?client=safari&rls=en&q=phfetchoptions+predicate+title&ie=UTF-8&oe=UTF-8 + // So we fetch all, and filter ourselves. + let result = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .albumRegular, options: nil) + + // Now, for each matching album, fetch images + result.enumerateObjects { assetCollection, _, stopPointer in + if assetCollection.localizedTitle == configuration.albumName { + // We may have multiple ioLight albums. I don't quite know how this happens; I think it's when they are + // aded on different devices and synced by iCloud. The only reasonable thing to do is to collate them + fetch(withConfiguration: configuration, + assetCollection: assetCollection) { albumAssets in + albumAssets.forEach { asset in + assets.insert(asset, at: 0) + } + } + } + } + + completion(assets) + } + + private static func fetch(withConfiguration configuration: ImagePickerConfiguration, + assetCollection: PHAssetCollection? = nil, + _ completion: @escaping (_ assets: [PHAsset]) -> Void) { + let assetOptions = PHFetchOptions() + if !configuration.allowVideoSelection { + assetOptions.predicate = NSPredicate(format: "mediaType = \(PHAssetMediaType.image.rawValue)") + } + + var fetchResult: PHFetchResult! + if let assetCollection = assetCollection { + fetchResult = PHAsset.fetchAssets(in: assetCollection, options: assetOptions) + } else { + fetchResult = PHAsset.fetchAssets(with: assetOptions) + } + + var assets = [PHAsset]() + + if fetchResult.count > 0 { + fetchResult.enumerateObjects({ object, _, _ in + assets.insert(object, at: 0) + }) + } + + completion(assets) + } + + // Fetch all assets public static func fetch(withConfiguration configuration: ImagePickerConfiguration, _ completion: @escaping (_ assets: [PHAsset]) -> Void) { guard PHPhotoLibrary.authorizationStatus() == .authorized else { return } DispatchQueue.global(qos: .background).async { - let fetchResult = configuration.allowVideoSelection - ? PHAsset.fetchAssets(with: PHFetchOptions()) - : PHAsset.fetchAssets(with: .image, options: PHFetchOptions()) - - if fetchResult.count > 0 { - var assets = [PHAsset]() - fetchResult.enumerateObjects({ object, _, _ in - assets.insert(object, at: 0) - }) - - DispatchQueue.main.async { - completion(assets) + fetchFromAlbum(withConfiguration: configuration) { assets in + if !assets.isEmpty { + DispatchQueue.main.async { + completion(assets) + } } } } } - + public static func resolveAsset(_ asset: PHAsset, size: CGSize = CGSize(width: 720, height: 1280), shouldPreferLowRes: Bool = false, completion: @escaping (_ image: UIImage?) -> Void) { let imageManager = PHImageManager.default() let requestOptions = PHImageRequestOptions() diff --git a/Source/Configuration.swift b/Source/Configuration.swift index 0928768c..d1660fc1 100644 --- a/Source/Configuration.swift +++ b/Source/Configuration.swift @@ -54,6 +54,7 @@ import UIKit @objc public var allowVolumeButtonsToTakePicture = true @objc public var useLowResolutionPreviewImage = false @objc public var galleryOnly = false + @objc public var albumName : String? = nil // MARK: Images @objc public var indicatorView: UIView = {