5
votes

The app can create a custom album in the standard iOS photos application, but I have been unable to find a way for the app to gather all the images from that album to be displayed within the app.

Currently, the app is able to gather images from all the albums, just not one is particular.

let resultCollections = PHAssetCollection.fetchAssetCollectionsWithType(
                 .Album,
        subtype: .AlbumRegular,
        options: nil)

    resultCollections.enumerateObjectsUsingBlock({
        (object, index, stop) -> Void in

        let collection = object as! PHAssetCollection
        let result = PHAsset.fetchAssetsInAssetCollection(collection, options: nil)

        result.enumerateObjectsUsingBlock({
            (object, index, stop) -> Void in

            let asset = object as! PHAsset
            self.images.append(asset)

        })

    })

I have seen other questions that might be marked as duplicates, however the majority of them are talking about opening a UIPickerView to a custom album. This is a possible duplicate of How to fetch all images from custom Photo Album - swift however, it was never answered.

So, how can an iOS app gather all images from a particular photos album?

3
What problem are you having with your existing code?jtbandes
@jtbandes The code included works fine (for gathering all photos in any album), however I am looking for only a specific album's photosrcobelli
Which album? How do you identify the album? It seems your code already fetches photos in an album, you just need to choose the album.jtbandes
@jtbandes I need it to select all photos from only a certain album, named 'XYZ'. Currently, it just selects all image in any albumrcobelli

3 Answers

11
votes

Add fetchOptions like below

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", YourAlbumTitle)
let resultCollections = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: fetchOptions)

Actually, album title isn't unique value, they can duplicate. so I recommend use localIdentifier like below, if your app access multiple albums.

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "localIdentifier = %@", YourAlbumLocalIdentifier)
let resultCollections = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .AlbumRegular, options: fetchOptions)
8
votes

Working Code For Swift 4

My Answer might help you and others(https://stackoverflow.com/a/35178022/4795651) but then also adding the code here..!!

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)

}
1
votes

class AlbumModel { let name:String let count:Int let asset:NSMutableArray init(name:String, count:Int, asset:NSMutableArray) { self.name = name self.count = count self.asset = asset } } class yourCustomCell: UITableViewCell {

//MARK:- Properties

@IBOutlet weak var collectionView: UICollectionView!

//MARK:- initialization methods

override func awakeFromNib() {
    super.awakeFromNib()
  //  setupView()
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

}

//MARK:- Setup collectionView datasource and delegate

func setCollectionViewDataSourceDelegate<T:UICollectionViewDataSource & UICollectionViewDelegate>(dataSourceDelegate: T, forRow row: Int) {
    collectionView.delegate = dataSourceDelegate
    collectionView.dataSource = dataSourceDelegate
    collectionView.tag = row
    collectionView.reloadData()
}

}

class ViewController: UIViewController {

 var tablearray = NSMutableArray()
func getAssetThumbnail(asset: PHAsset) -> UIImage {
    let manager = PHImageManager.default()
    let option = PHImageRequestOptions()
    var thumbnail = UIImage()
    option.isSynchronous = true
    manager.requestImage(for: asset, targetSize: CGSize(width: 100, height: 100), contentMode: .aspectFit, options: option, resultHandler: {(result, info)->Void in
        thumbnail = result!
    })
    return thumbnail
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    //print(UnladenSwallow.unknown)

    let fetchOptions = PHFetchOptions()

    let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: fetchOptions)

    let topLevelfetchOptions = PHFetchOptions()

    let topLevelUserCollections = PHCollectionList.fetchTopLevelUserCollections(with: topLevelfetchOptions)

    let allAlbums = [topLevelUserCollections, smartAlbums]


    var name = ""

    smartAlbums.enumerateObjects({
        if let collection = $0.0 as? PHAssetCollection{

            name = collection.localizedTitle!

            let image_arry = NSMutableArray()
            let result = PHAsset.fetchAssets(in: collection, options: nil)
            result.enumerateObjects({ (object, index, stop) -> Void in
                let asset = object 
                image_arry.add(self.getAssetThumbnail(asset: asset))
            })
            let newAlbum = AlbumModel(name: name, count: collection.estimatedAssetCount, asset:image_arry)
            self.tablearray.add(newAlbum)
        }
    })

    topLevelUserCollections.enumerateObjects({
        if let collection = $0.0 as? PHAssetCollection{

            name = collection.localizedTitle!

            let image_arry = NSMutableArray()
            let result = PHAsset.fetchAssets(in: collection, options: nil)
            result.enumerateObjects({ (object, index, stop) -> Void in
                let asset = object
                image_arry.add(self.getAssetThumbnail(asset: asset))
            })
            let newAlbum = AlbumModel(name: name, count: collection.estimatedAssetCount, asset:image_arry)
            self.tablearray.add(newAlbum)
        }
    })

    print(self.tablearray)

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

extension ViewController: UITableViewDataSource,UITableViewDelegate{

func numberOfSections(in tableView: UITableView) -> Int{
    return self.tablearray.count
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    let album =  self.tablearray[section] as! AlbumModel
    return album.name
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! yourCustomCell
    cell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: indexPath.section)

    return cell
}

} extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    let album =  self.tablearray[collectionView.tag] as! AlbumModel
    print("count = \(album.asset.count)")
    return album.asset.count;
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let album =  self.tablearray[collectionView.tag] as! AlbumModel
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "col", for: indexPath)
    let img = cell.viewWithTag(111) as! UIImageView
    img.image =  album.asset.object(at: indexPath.row) as? UIImage

    return cell

}

}

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: IndexPath) {

print("get selected collectionview itemindex \(indexPath.row)")

}