I am following Apple's Sample code 'ExampleappusingPhotosframework'.
In the subject of PHAssets/PHAssetCollection, I noticed there is the possibility of 'Folders' being present. These can appear from being created be Mac's Photo's App, or an older iPhoto app, ect....
There are possibilities of a folder being present amount PHAssetCollection's and that folder can contain unknown levels of nested folders, ending with an Album(s) at the end.
So, even above sample project crashes if I have nested folders in the photo library. Most app's just seem to ignore and not show these folders at all.
For an example lets say this example exists:
Folder Level 1 > Folder Level 2 > Custom Album > Image1, Image2
How iOS Photos App Handles it:
Task
In the Root Album list, under user albums, "Folder Level 1" should be seen. When that's tapped, I want to list all the images from all the sub folders regardless of sub levels.....
viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(self.addAlbum))
self.navigationItem.rightBarButtonItem = addButton
// Create a PHFetchResult object for each section in the table view.
let allPhotosOptions = PHFetchOptions()
allPhotosOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
allPhotos = PHAsset.fetchAssets(with: allPhotosOptions)
smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
PHPhotoLibrary.shared().register(self)
}
cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch Section(rawValue: indexPath.section)! {
case .allPhotos:
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.allPhotos.rawValue, for: indexPath)
cell.textLabel!.text = NSLocalizedString("All Photos", comment: "")
return cell
case .smartAlbums:
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.collection.rawValue, for: indexPath)
let collection = smartAlbums.object(at: indexPath.row)
cell.textLabel!.text = collection.localizedTitle
return cell
case .userCollections:
let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifier.collection.rawValue, for: indexPath)
let collection = userCollections.object(at: indexPath.row)
cell.textLabel!.text = collection.localizedTitle
return cell
}
}
Segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = (segue.destination as? UINavigationController)?.topViewController as? AssetGridViewController
else { fatalError("unexpected view controller for segue") }
let cell = sender as! UITableViewCell
destination.title = cell.textLabel?.text
switch SegueIdentifier(rawValue: segue.identifier!)! {
case .showAllPhotos:
destination.fetchResult = allPhotos
case .showCollection:
// get the asset collection for the selected row
let indexPath = tableView.indexPath(for: cell)!
let collection: PHCollection
switch Section(rawValue: indexPath.section)! {
case .smartAlbums:
collection = smartAlbums.object(at: indexPath.row)
case .userCollections:
collection = userCollections.object(at: indexPath.row)
default: return // not reached; all photos section already handled by other segue
}
// configure the view controller with the asset collection
guard let assetCollection = collection as? PHAssetCollection
else { fatalError("expected asset collection") }
destination.fetchResult = PHAsset.fetchAssets(in: assetCollection, options: nil)
destination.assetCollection = assetCollection
}
}
Question
assetCollection?.canContainCollections seems to be the deciding factor. However, how would I fetch all the containing PHAssets within the folder, regardless of the sub-levels/sub-folders? (This cannot be impossible since even the stock app has "All Photos" inside level 1)