MacOS PhotoKit - List all user-created Smart Albums?

804 views Asked by At

I've started playing around with macOS development for the first time. I'm trying to query the list of Smart Albums I've created in the macOS Photos app. As you can see in this screenshot, I've defined 18 Smart Albums and 1 regular Album.

Screenshot of the Albums

However, when I fetch the Smart Album PHAssetCollections I do not see the Smart Albums I've defined. Here is the code I'm using to fetch a total photo count, the Smart Albums, and then normal Albums:

let allPhotosOptions = PHFetchOptions()
allPhotosOptions.includeAssetSourceTypes = [.typeUserLibrary]

allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
let allPhotos = PHAsset.fetchAssets(with: allPhotosOptions)
let photoCount = allPhotos.count
print("photoCount=\(photoCount)")

print("***********************************")
print("Smart Albums")
print("***********************************")

let smartAlbumsOptions = PHFetchOptions()
smartAlbumsOptions.includeAssetSourceTypes = [.typeUserLibrary]
let smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .any, options: smartAlbumsOptions)
let smartAlbumCount = smartAlbums.count
print("smartAlbumCount=\(smartAlbumCount)")
smartAlbums.enumerateObjects { (collection, index, stop) in
    print("Collection \(index + 1):")
    print("\tlocalizedTitle=\(String(describing: collection.localizedTitle))")
    print("\tassetCollectionType=\(collection.assetCollectionType)")
    print("\testimatedAssetCount=\(collection.estimatedAssetCount)")
    print("\tstartDate=\(String(describing: collection.startDate)), endDate=\(String(describing: collection.endDate))")
}

print("***********************************")
print("Albums")
print("***********************************")

let albums = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: nil)
let albumCount = albums.count
print("albumCount=\(albumCount)")
albums.enumerateObjects { (collection, index, stop) in
    print("Collection \(index + 1):")
    print("\tlocalizedTitle=\(String(describing: collection.localizedTitle))")
    print("\tassetCollectionType=\(collection.assetCollectionType)")
    print("\testimatedAssetCount=\(collection.estimatedAssetCount)")
    print("\tstartDate=\(String(describing: collection.startDate)), endDate=\(String(describing: collection.endDate))")
}

However, when I run this code I see the following output, showing that my user-created Smart Albums are not being returned:

2020-05-23 16:41:31.059604-0400 PhotoKitTest[40065:709882] Metal API Validation Enabled
2020-05-23 16:41:33.027378-0400 PhotoKitTest[40065:709882] [core] "Error returned from daemon: Error Domain=com.apple.accounts Code=7 "(null)""
photoCount=25369
***********************************
Smart Albums
***********************************
smartAlbumCount=15
Collection 1:
    localizedTitle=Optional("Bursts")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=Optional(2017-03-13 14:50:57 +0000), endDate=Optional(2018-08-29 15:15:03 +0000)
Collection 2:
    localizedTitle=Optional("Slo-mo")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 3:
    localizedTitle=Optional("Screenshots")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=Optional(2015-10-22 13:51:51 +0000), endDate=Optional(2020-05-21 14:39:40 +0000)
Collection 4:
    localizedTitle=Optional("Animated")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 5:
    localizedTitle=Optional("Live Photos")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 6:
    localizedTitle=Optional("Unable to Upload")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 7:
    localizedTitle=Optional("Panoramas")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=Optional(2015-06-29 22:14:27 +0000), endDate=Optional(2015-07-26 19:28:39 +0000)
Collection 8:
    localizedTitle=Optional("Videos")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=Optional(2004-11-11 01:03:36 +0000), endDate=Optional(2020-05-23 14:52:01 +0000)
Collection 9:
    localizedTitle=Optional("Hidden")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 10:
    localizedTitle=Optional("Selfies")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=Optional(2011-08-06 13:17:49 +0000), endDate=Optional(2020-05-21 14:33:38 +0000)
Collection 11:
    localizedTitle=Optional("Favorites")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 12:
    localizedTitle=Optional("Time-lapse")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 13:
    localizedTitle=Optional("Portrait")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 14:
    localizedTitle=Optional("Long Exposure")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=nil, endDate=nil
Collection 15:
    localizedTitle=Optional("Recents")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=9223372036854775807
    startDate=Optional(2001-09-22 16:05:17 +0000), endDate=Optional(2020-05-23 14:52:01 +0000)
***********************************
Albums
***********************************
albumCount=1
Collection 1:
    localizedTitle=Optional("My Test Album")
    assetCollectionType=PHAssetCollectionType
    estimatedAssetCount=0
    startDate=nil, endDate=nil

As you can see, my normal album My Test Album is returned, but none of the Smart Albums I created, such as those for 2008, 2009, etc. Am I doing something wrong? Do I need an additional value in my Info.plist beyond including NSPhotoLibraryUsageDescription? This is my first time playing around with the PhotoKit framework so I'm sure I may be misunderstanding something. But, I thought this was a pretty simple use case. I'm running this on macOS Catalina, using Xcode 11.5 and Swift.

1

There are 1 answers

1
zrzka On BEST ANSWER

TL;DR - It's not possible.


  • built-in smart album = Selfies, Panoramas, Screenshots, ...
  • smart album = custom smart album created on a Mac

Apple introduced the Photos app (iPhoto successor) quite a long time ago. And it was, still is, fairly limited if you're an advanced user requiring smart albums, keywords, ... Open the Photos app on your phone - there're no smart albums. Visit iCloud Photos - there're no smart albums. They're not synced1.

When you check the smartAlbum documentation, it says:

The Photos app displays built-in smart albums to group certain kinds of related assets.

I don't know why they're talking about the Photos app in the Photos.framework documentation, it's not super clear, but it kind of gives you a clue that the smartAlbum is about built-in smart albums.

There's also the smartAlbumGeneric subtype documentation:

This subtype applies to smart albums synced to the iOS device from the macOS Photos app.

But there're no smart albums synced to the iOS device. It's an empty list if you will try to use this one.

It's somehow limited because of iCloud Photos (IMHO). There's an analogy in another framework - CoreData + iCloud support imposes some limits of what you can do and it's less powerful than just CoreData (without iCloud). But it's a pure speculation. Maybe all your smart albums will appear in the list if you turn off iCloud Photos (Photos - Preferences... - iCloud - iCloud Photos), but I'm not that brave to try it as I do not want download the whole library again or to loose something.

Do you want to access your smart album? Some workarounds:


1 Actually they're synced, but you can see them on your Mac(s) only.