I am developing an app basing on Photos
framework. However, I find that Photos
framework is something mainly for Photos.app and not well documented.
I will listed them for further references.
System Default Alert Message May Confuse Users.
When removing an album from photo library, you must use class func deleteAssetCollections(_ assetCollections: NSFastEnumeration)
. The system will automatically represents an alert to ask the user whether to remove the album. However, there is a message says that only the album is removed, the photos inside the album are kept.
The message is accurate for Photos.app. However, if we want to remove the photos together with the album, there is no API for that, so we have to call the remove API twice, one for photos, the other for album. There will be two alerts shown and the alert message mentioned may confuse the user as the photos are removed this time.
Folders
Folder can contain other Folders, but not its parents.
Folder, which is called PHCollectionList
is said can contain other folders. That leads me to say what if folder A contains folder B and B contains A, which make the relation recursive. So I created an example, and I found that when A contains B and B contains A, photo library would rise an error. So the recursive relation is not allowed.
The Collection operations are all movement, not copying.
When putting other collections into one folder, whether you use addChildCollections(_:)
or insertChildCollections(_:at:)
is irrelevant. The collections are just moved inside the folder, not copied.
This rule also makes there is not duplicated folders in photo library.
fetchCollections(in:options:)
is shallow.
The result of Although fetchCollections(in:options:) says it returns "By default, the returned PHFetchResult object contains all collections in the specified collection list." The document is not accurate. It only returns the shallow collections, not all collections. For example, we have three folders, A, B and C. The relations of them is: A -> B -> C, A contains B, B contains C.
let collections = PHCollection.fetchCollections(in: A, options: nil)
print(collections.count)
// 1. Print 1 instead of 2. As folder B is the only collection with shallow search.
Other constrains of folder operations
PHPhotoLibrary.shared().performChanges {
let requestA = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: "FolderA")
let requestB = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: "FolderB")
let folderB = requestB.placeholderForCreatedCollectionList
let requestC = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: "FolderC")
let folderC = requestC.placeholderForCreatedCollectionList
requestA.addChildCollections([folderB] as NSFastEnumeration) // move B to A, works
requestB.addChildCollections([folderC] as NSFastEnumeration) // move C to B, works
requestA.addChildCollections([folderC] as NSFastEnumeration) // move C to A, doesn't work
} completionHandler: { success, error in
if success {
print("success")
} else {
print(error?.localizedDescription ?? "nil")
}
}
Result in Photos.app: A -> B -> C
Line 9 doesn't work. I guess because C has been already in A by contained by B.
However, code below works.
PHPhotoLibrary.shared().performChanges {
let requestA = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: "FolderA")
let requestB = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: "FolderB")
let folderB = requestB.placeholderForCreatedCollectionList
let requestC = PHCollectionListChangeRequest.creationRequestForCollectionList(withTitle: "FolderC")
let folderC = requestC.placeholderForCreatedCollectionList
requestA.addChildCollections([folderB] as NSFastEnumeration) // move B to A, works
requestA.addChildCollections([folderC] as NSFastEnumeration) // move C to A, works
requestB.addChildCollections([folderC] as NSFastEnumeration) // move C to B, works
} completionHandler: { success, error in
if success {
print("success")
} else {
print(error?.localizedDescription ?? "nil")
}
}
Apple avoids structural complexity by design.
In Photos.app on macOS, you can only move the collections besides the target folder on the same level. This avoid the complexity of the model structure. In fact, you can move any folder to the target folder. However, that will make not every move operation working, which may confuse user that doesn't familiar with the rules.