PHAssets/PHAssetCollection/PHCollectionList и папки

Я слежу за примером кода Apple " ExampleappusingPhotosframework ".

В теме PHAssets/PHAssetCollection я заметил, что существует возможность присутствия " Папок ". Они могут появиться из того, что они были созданы в приложении Mac's Photo или более старом приложении iPhoto, и т. Д.

Существуют возможности присутствия папки в количестве PHAssetCollection, и эта папка может содержать неизвестные уровни вложенных папок, заканчиваясь альбомом (ами) в конце.

Таким образом, даже выше пример проекта падает, если у меня есть вложенные папки в библиотеке фотографий. Большинство приложений просто игнорируют и не показывают эти папки вообще.

Для примера допустим, что этот пример существует:

введите описание изображения здесь

Уровень папки 1 > Уровень папки 2 > Пользовательский альбом> Изображение1, Изображение2

Как iOS Photos App справляется с этим:

введите описание изображения здесь

задача

В списке корневых альбомов под альбомами пользователей должен быть виден "Уровень папки 1". После этого я хочу перечислить все изображения из всех вложенных папок независимо от подуровней.....

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
    }
}

Вопрос

assetCollection?. canContainCollections, кажется, является решающим фактором. Тем не менее, как мне получить все содержащие PHAssets в папке, независимо от подуровней / подпапок? (Это не может быть невозможно, так как даже в стандартном приложении есть "Все фотографии" внутри уровня 1)

1 ответ

Решение

С текущими API разработчика (PhotoKit) нет простого способа (как с одним запросом) перечислить все активы в папке (и ее подпапках / альбомах). Однако вы можете рекурсивно перечислить все альбомы в папке и ее подпапках, а затем поместить результаты в один массив. Это, однако, может быть медленным в зависимости от количества уровней и активов, содержащихся во вложенной структуре. Обратите внимание, что папка любого уровня также может содержать альбом (например, на "уровне папки 1" также может быть альбом в дополнение к папке "уровня папки 2"). Приложение Apple Photos не использует PhotoKit, поэтому я предполагаю, что у них есть способ сделать это с помощью одного запроса.

Другие вопросы по тегам