Hikarus
Hikarus

Reputation: 335

Get photos from specific album in swift using PHAssetCollection.fetchAssetCollectionsWithType()

when I launch a photos fetch like:

let assetCollections: PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .Any, options: nil) 

I get a result of several albums, so I can iterate through the array and put their titles in a tableView.

BUT: when I use a predicate to filter and get for example the album "Camera Roll", the result is always an empty array: (And I know 100% sure that Camera Roll exists because with nil options it fetches it)

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %@", "Camera Roll")
let assetCollections: PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .Any, options: fetchOptions)
let album: PHAssetCollection = assetCollections.firstObject as! PHAssetCollection

I've read 4 or 5 different methods by people online, and they all have this predicate whether with "title = %@", or "localizedTitle = %@" or "localizedIdentifier = %@"... I DON'T GET IT. Seems to work for people, not for me. The compiler crashes at the last line trying to "unwrap a nil optional value" ('cos the fetch result is empty). Why is the search returning nil as soon as include the fetch options???

Upvotes: 2

Views: 5620

Answers (5)

Roman
Roman

Reputation: 1498

let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "localizedTitle = %@", "Camera Roll")
let assetCollections = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
let album = assetCollections.firstObject

Upvotes: 0

jamesthakid
jamesthakid

Reputation: 1265

If you want Camera Roll album only, you can try something like this :

func getCameraRoll() -> AlbumModel {
      var cameraRollAlbum : AlbumModel!

      let cameraRoll = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary, options: nil)

      cameraRoll.enumerateObjects({ (object: AnyObject!, count: Int, stop: UnsafeMutablePointer) in
        if object is PHAssetCollection {
          let obj:PHAssetCollection = object as! PHAssetCollection

          let fetchOptions = PHFetchOptions()
          fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
          fetchOptions.predicate = NSPredicate(format: "mediaType = %d", PHAssetMediaType.image.rawValue)
          let assets = PHAsset.fetchAssets(in: obj, options: fetchOptions)

          if assets.count > 0 {
            let newAlbum = AlbumModel(name: obj.localizedTitle!, count: assets.count, collection:obj, assets: assets)

            cameraRollAlbum = newAlbum
          }
        }
      })
     return cameraRollAlbum

    }

Note that you should AlbumModel is a model I created, you can change it and use your own data model.

Upvotes: 0

rickster
rickster

Reputation: 126127

If you want the Camera Roll album, you're probably better off asking for it symbolically:

let collections = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumUserLibrary, options: nil)

The SmartAlbumUserLibrary subtype is how you get the Camera Roll (which isn't always called that).

Upvotes: 6

yujean
yujean

Reputation: 795

Try the format:

fetchOptions.predicate = NSPredicate(format: "%K == %@", "title", "Camera Roll")

or

fetchOptions.predicate = NSPredicate(format: "%K LIKE[cd] %@", "title", "Camera Roll")

Upvotes: -1

Hikarus
Hikarus

Reputation: 335

the solution seems to be to use:

PHAssetCollection.fetchAssetCollectionsWithLocalizedIdentifiesr(identifiers: [String], options: PHFetchOptions)

So, passing into the parameter 'identifier' an array of strings with the titles of the albums we wish to fetch achieves the same result than attempting the predicate method that doesn't seem to work any more.

Upvotes: 1

Related Questions