iOS: работа с галереей (Photos framework)

в 10:01, , рубрики: gallery, iOS, Photos framework, swift, xcode, разработка мобильных приложений, разработка под iOS

Привет! В данной статье решил написать о том, как работать с галереей с помощью фреймворка Photos. В этой статье рассмотрим базовые возможности фреймворка: создание альбома, сохранение, удаление и загрузку фото. Если будут положительные отзывы, то в следующих частях напишу про работу с live фото, видео, наложение фильтров, кэш и прочие функции.

Обзор классов

Для начала рассмотрим классы, с которыми предстоит работать. Во фреймворке Photos все классы унаследованы от базового класса PHObject, в котором есть всего лишь одно свойство — localIdentifier.

▍PHAsset

PHAsset представляет собой данные об одном объекте из галереи — фото, видео, live фото и так далее. Важно понимать, что PHAsset это еще не фото, это только информация о нем.

▍PHAssetCollection

Это набор объектов PHAsset. Таким набором может быть альбом, момент, smart album.

▍PHPhotoLibrary

Это класс, который предоставляет доступ на запрос и изменение данных из галереи. Каждый раз, когда мы хотим что-то поменять в галерее, нам надо вызывать метод performChanges(changes: () → Void, completionHandler: (Bool, Error?) → Void).

▍PHAssetCreationRequest

Класс, позволяющий сделать запрос на создание нового объекта(PHAsset) в галерее.

▍PHAssetChangeRequest

Класс, позволяющий сделать запрос на изменение объекта в галерее.

▍PHAssetCollectionChangeRequest

Класс, позволяющий сделать запрос на изменение коллекции объектов в галерее.

▍PHImageManager

Позволяет получить фото или видео ассоциируемое с конкретным PHAsset.

▍PHFetchResult

Представляет обертку над списком PHAsset, полученных в результате запроса.

Создание альбома

Для начала нужно проверить — есть ли альбом с тем имением, с которым мы хотим его создать:

let options = PHFetchOptions()
options.predicate = NSPredicate(format: "title = %@", albumTitle)
let collection = PHAssetCollection.fetchAssetCollections(with: .album, 
                                                         subtype: .any, 
                                                         options: options)
if let album = collection.firstObject {
    // Альбом уже есть, можем его использовать
}

Если альбома нет, то для его создания нам потребуется создать запрос с помощью метода PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: String):

var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
    let request = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumTitle)
    placeholder = request.placeholderForCreatedAssetCollection
}, completionHandler: { (success, error) -> Void in
    if success {
        if let id = placeholder?.localIdentifier {
            let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [id], 
                                                                      options: nil)
            if let album = fetchResult.firstObject {
                // Можем использовать альбом
            }
        }
    }
})

PHObjectPlaceholder — это наследник PHObject, который по сути является прокси реального объекта, который был создан(в нашем случае это альбом). Нужен он для того, чтобы получить ID созданного объекта.

Получение списка PHAsset

Итак, мы получили альбом(а точнее PHAssetCollection), который хранит объекты PHAsset. Мы можем получить все PHAsset следующим образом:

let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: ascending)]

let assets: PHFetchResult<PHAsset> = PHAsset.fetchAssets(in: album, options: options)

Переменная assets будет хранить список PHAsset отсортированный по возрастанию даты создания фото. Конкретный PHAsset мы можем получить, например, так:

if assets.count > 0 {
    let firstAsset = assets[0]
}

Получение UIImage

Чтобы загрузить изображение для конкретного PHAsset нам понадобится класс PHImageManager:

PHImageManager.default().requestImage(for: asset,
                                      targetSize: size,
                                      contentMode: .aspectFill,
                                      options: options) { (image, _) -> Void in
                                          // Можем использовать изображение
                                      }

Сохранение изображения

Для того, чтобы сохранить изображение, надо создать запрос методом PHAssetChangeRequest.creationRequestForAsset(from image: UIImage):

PHPhotoLibrary.shared().performChanges({
    let assetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
    let albumChangeRequest = PHAssetCollectionChangeRequest(for: album, assets: assets)
    if let assetPlaceholder = assetRequest.placeholderForCreatedAsset {
        let assetPlaceholders: NSArray = [assetPlaceholder]
        albumChangeRequest?.addAssets(assetPlaceholders)
    }
}, completionHandler: nil)

Удаление PHAsset

Вот мы и добрались до самого сложного. Для удаления PHAsset нам понадобится метод PHAssetChangeRequest.deleteAssets(_ assets: NSFastEnumeration):

PHPhotoLibrary.shared().performChanges({
    PHAssetChangeRequest.deleteAssets(assets as NSFastEnumeration)
}, completionHandler: nil)

Заключение

Я описал базовые возможности фреймворка. В дальнейшем напишу статьи по другим его возможностям. Все что непонятно — спрашивайте в комментариях. Любая критика приветствуется.

Полезные ссылки

» Photos framework reference | Apple
» The Photos Framework | objc.io

Автор: NoFearJoe

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js