How to fetch all images from custom Photo Album - Swift
For Swift 4
using this answer https://stackoverflow.com/a/28904792/4795651 edited a little for myself.
import Photos
func fetchCustomAlbumPhotos()
{
let albumName = "Album Name Here"
var assetCollection = PHAssetCollection()
var albumFound = Bool()
var photoAssets = PHFetchResult<AnyObject>()
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let firstObject = collection.firstObject{
//found the album
assetCollection = firstObject
albumFound = true
}
else { albumFound = false }
_ = collection.count
photoAssets = PHAsset.fetchAssets(in: assetCollection, options: nil) as! PHFetchResult<AnyObject>
let imageManager = PHCachingImageManager()
photoAssets.enumerateObjects{(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset{
let asset = object as! PHAsset
print("Inside If object is PHAsset, This is number 1")
let imageSize = CGSize(width: asset.pixelWidth,
height: asset.pixelHeight)
/* For faster performance, and maybe degraded image */
let options = PHImageRequestOptions()
options.deliveryMode = .fastFormat
options.isSynchronous = true
imageManager.requestImage(for: asset,
targetSize: imageSize,
contentMode: .aspectFill,
options: options,
resultHandler: {
(image, info) -> Void in
self.photo = image!
/* The image is now available to us */
self.addImgToArray(uploadImage: self.photo!)
print("enum for image, This is number 2")
})
}
}
}
func addImgToArray(uploadImage:UIImage)
{
self.images.append(uploadImage)
}
For Swift 2.1
import Photos
func FetchCustomAlbumPhotos()
{
var albumName = "SwiftAlbum"
var assetCollection = PHAssetCollection()
var albumFound = Bool()
var photoAssets = PHFetchResult()
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", albumName)
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)
if let first_Obj:AnyObject = collection.firstObject{
//found the album
assetCollection = collection.firstObject as! PHAssetCollection
albumFound = true
}
else { albumFound = false }
var i = collection.count
photoAssets = PHAsset.fetchAssetsInAssetCollection(assetCollection, options: nil)
let imageManager = PHCachingImageManager()
// let imageManager = PHImageManager.defaultManager()
photoAssets.enumerateObjectsUsingBlock{(object: AnyObject!,
count: Int,
stop: UnsafeMutablePointer<ObjCBool>) in
if object is PHAsset{
let asset = object as! PHAsset
print("Inside If object is PHAsset, This is number 1")
let imageSize = CGSize(width: asset.pixelWidth,
height: asset.pixelHeight)
/* For faster performance, and maybe degraded image */
let options = PHImageRequestOptions()
options.deliveryMode = .FastFormat
options.synchronous = true
imageManager.requestImageForAsset(asset,
targetSize: imageSize,
contentMode: .AspectFill,
options: options,
resultHandler: {
(image, info) -> Void in
self.photo = image!
/* The image is now available to us */
self.addImgToArray(self.photo)
print("enum for image, This is number 2")
})
}
}
}
func addImgToArray(uploadImage:UIImage)
{
self.images.append(uploadImage)
}
This is a custom album, so what you've got to do is to add it to your code in the middle:
import Photos
class CustomPhotoAlbum {
static let albumName = "Album"
static let sharedInstance = CustomPhotoAlbum()
var assetCollection: PHAssetCollection!
init() {
func fetchAssetCollectionForAlbum() -> PHAssetCollection! {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", CustomPhotoAlbum.albumName)
let collection = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let firstObject: AnyObject = collection.firstObject {
return collection.firstObject as? PHAssetCollection
}
return nil
}
if let assetCollection = fetchAssetCollectionForAlbum() {
self.assetCollection = assetCollection
return
}
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: CustomPhotoAlbum.albumName)
}) { success, _ in
if success {
self.assetCollection = fetchAssetCollectionForAlbum()
}
}
}
func saveImage(image: UIImage) {
if assetCollection == nil {
return // If there was an error upstream, skip the save.
}
PHPhotoLibrary.shared().performChanges({
let assetChangeRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetPlaceholder = assetChangeRequest.placeholderForCreatedAsset
let albumChangeRequest = PHAssetCollectionChangeRequest(for: self.assetCollection)
albumChangeRequest?.addAssets([assetPlaceholder] as NSFastEnumeration)
}, completionHandler: nil)
}
}
Then to fetch all the pics in your album use this code:
func getAlbum(title: String, completionHandler: @escaping (PHAssetCollection?) -> ()) {
DispatchQueue.global(qos: .background).async { [weak self] in
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", title)
let collections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
if let album = collections.firstObject {
completionHandler(album)
} else {
self?.createAlbum(withTitle: title, completionHandler: { (album) in
completionHandler(album)
})
}
}
}
To call this function use this example:
getAlbum(title: "Album") { [weak self] assetCollection in
guard let this = self else { return }
guard assetCollection != nil else { return }
print(assetCollection!)
}
If you want to create a custom album use this function:
func createAlbum(withTitle title: String, completionHandler: @escaping (PHAssetCollection?) -> ()) {
DispatchQueue.global(qos: .background).async {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: title)
placeholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { (created, error) in
var album: PHAssetCollection?
if created {
let collectionFetchResult = placeholder.map { PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [$0.localIdentifier], options: nil) }
album = collectionFetchResult?.firstObject
}
completionHandler(album)
})
}
}
This function will be called in the getAlbum, if the album isn't created.
Try this to get Photos from a specific Album
func get_Photos_From_Album(albumName: String)
{
var photoLibraryImages = [UIImage]()
var photoLibraryAssets = [PHAsset]()
//whatever you need, you can use UIImage or PHAsset to photos in UICollectionView
DispatchQueue.global(qos: .userInteractive).async
{
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: nil)
let customAlbums = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
[smartAlbums, customAlbums].forEach {
$0.enumerateObjects { collection, index, stop in
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
let photoInAlbum = PHAsset.fetchAssets(in: collection, options: fetchOptions)
if let title = collection.localizedTitle
{
if photoInAlbum.count > 0
{
print("\n\n \(title) --- count = \(photoInAlbum.count) \n\n")
}
if title == albumName
{
if photoInAlbum.count > 0
{
for i in (0..<photoInAlbum.count).reversed()
{
imgManager.requestImage(for: photoInAlbum.object(at: i) as PHAsset , targetSize: CGSize(width: 150, height: 150), contentMode: .aspectFit, options: requestOptions, resultHandler: {
image, error in
if image != nil
{
photoLibraryImages.append(image!)
photoLibraryAssets.append(photoInAlbum.object(at: i))
}
})
}
}
}
}
}
}
}
}