PhotoKit — это фреймворк Apple для работы с медиатекой на iOS и macOS, предоставляющий прямой доступ к фото, видео и Live Photos на устройстве. По данным документации Apple, фреймворк заменяет устаревший AssetsLibrary и поддерживает iCloud, альбомы, редактирование и Change Tracking. PhotoKit обеспечивает единый API для запросов, кэширования и изменений медиатеки с автоматической синхронизацией через iCloud.
Главное
PhotoKit — фреймворк Apple (представленный в iOS 8, macOS 10.11), предоставляющий объектно-ориентированный API для работы с системной медиатекой. В отличие от AssetsLibrary, PhotoKit работает с медиатекой как с базой данных: запросы возвращают объекты PHAsset, PHCollection, PHCollectionList, представляющие содержимое и структуру хранения.
PhotoKit поддерживает все типы медиа: фотографии (JPEG, HEIF, RAW), видео (MOV, MP4), Live Photos и серийные снимки. Фреймворк автоматически управляет iCloud-синхронизацией: если изображение хранится в iCloud, PhotoKit запрашивает его через сеть и сообщает прогресс через PHImageRequestOptions.progressHandler.
Ключевая особенность PhotoKit — модель данных на основе PHObject с локальным идентификатором (localIdentifier), который остаётся стабильным между сессиями. Это позволяет сохранять ссылки на медиа-объекты и восстанавливать их после перезапуска приложения без повторного запроса.
PhotoKit построен на трёх уровнях: модели данных (PHObject), запросов (PHFetchResult) и изменений (PHPhotoLibrary.performChanges). Модель данных иерархическая: PHAsset (фото/видео) находится внутри PHAssetCollection (альбом), альбомы группируются в PHCollectionList (папка).
Запросы выполняются через PHAsset.fetchAssets и PHAssetCollection.fetchAssetCollections. Все методы fetch — синхронные и возвращают PHFetchResult, объект которого сразу выполняет запрос к базе данных медиатеки. PHFetchResult поддерживает быстрый доступ по индексу (object(at:)) и перечисление через enumerateObjects.
PHFetchOptions — объект для конфигурации запроса: сортировка (sortDescriptors), предикат (predicate), включение скрытых и удалённых медиа (includeHiddenAssets, includeAllBurstAssets). Фетч-опции позволяют фильтровать по типу медиа: PHAssetMediaType.image, .video, .audio.
PhotoKit включает набор классов для доступа, запросов и изменения медиатеки. Понимание каждого из них необходимо для эффективной работы с фреймворком.
PHAsset — неизменяемый объект, представляющий одно медиа-содержимое. Содержит метаданные: mediaType, mediaSubtypes, creationDate, location, pixelWidth, pixelHeight, duration (для видео), isFavorite, burstIdentifier. LocalIdentifier — стабильный строковый ключ, доступный даже после перезапуска приложения.
PHAssetCollection — группа медиа: системные альбомы (Recents, Favorites, Selfies, Screenshots), пользовательские альбомы или Moments (автоматически сгруппированные по времени и месту). Атрибуты: localizedTitle, assetCollectionType, assetCollectionSubtype, startDate, endDate.
PHCollectionList — папка, содержащая альбомы (PHAssetCollection) или другие папки. Используется редко, в основном для отображения иерархии в пользовательском интерфейсе.
PhotoKit не возвращает UIImage напрямую из PHAsset — нужно запросить изображение через PHImageManager. Это гарантирует, что изображение загружается с учётом iCloud, кэширования и требуемого размера.
| Компонент | Назначение | Особенность |
|---|---|---|
| PHImageManager.default() | Стандартный менеджер для разовых запросов | Нет кэширования между запросами |
| PHCachingImageManager | Менеджер с предзагрузкой для коллекций | startCachingImages для плавного скролла |
| PHImageRequestOptions | Настройки запроса: размер, режим, доставка | synchronous, deliveryMode, progressHandler |
| PHImageRequestID | Идентификатор запроса для отмены | cancelImageRequest(PHImageRequestID) |
PHImageManager поддерживает три режима доставки: opportunistic (сначала уменьшенная версия, затем полная), highQualityFormat (только полное качество) и fastFormat (самая быстрая доступная версия). Для коллекций всегда используйте PHCachingImageManager с предзагрузкой изображений для видимых ячеек.
PhotoKit используется для создания пользовательских галерей, редакторов и приложений для работы с медиа. Рассмотрим три ключевых сценария.
PHAsset.fetchAssets с PHFetchOptions и сортировкой по дате создания — базовый запрос для построения пользовательской фотогалереи. PHFetchResult поддерживает lazy-loading и потоковый доступ.
let options = PHFetchOptions()
options.sortDescriptors = [NSSortDescriptor(
key: "creationDate",
ascending: .false
)]
options.predicate = NSPredicate(
format: "mediaType == %d",
PHAssetMediaType.image.rawValue
)
let allPhotos = PHAsset.fetchAssets(with: options)
print("Found \(allPhotos.count) photos")
allPhotos.enumerateObjects { asset, index, stop in
print("Photo \(index): \(asset.localIdentifier)")
}
PHFetchResult — потокобезопасный контейнер. Доступ к объектам по индексу через object(at:) не блокирует UI, но запрос изображения через PHImageManager должен выполняться асинхронно.
PHCachingImageManager — подкласс PHImageManager с методами startCachingImages и stopCachingImages для предзагрузки. Используется в UICollectionView для плавного скролла.
let cachingManager = PHCachingImageManager()
let targetSize = CGSize(width: 200, height: 200)
// Предзагрузка для видимых ячеек
cachingManager.startCachingImages(
for: visibleAssets,
targetSize: targetSize,
contentMode: .aspectFill,
options: nil
)
// Запрос изображения через PHImageRequestOptions с iCloud fallback
let requestOptions = PHImageRequestOptions()
requestOptions.deliveryMode = .opportunistic
requestOptions.isNetworkAccessAllowed = .true
requestOptions.progressHandler = { progress, error, stop, info in
DispatchQueue.main.async {
print("Downloading from iCloud: \(progress * 100)%")
}
}
let requestID = cachingManager.requestImage(
for: asset,
targetSize: targetSize,
contentMode: .aspectFill,
options: requestOptions
) { image, info in
print("Got image: \(image?.size ?? .zero)")
}
Изменения в медиатеке выполняются через PHPhotoLibrary.shared().performChanges внутри блока changeRequest. Все операции батчатся и применяются транзакционно.
PHPhotoLibrary.shared().performChanges {
let changeRequest = PHAssetChangeRequest(for: asset)
changeRequest.isFavorite = .true
} completionHandler: { success, error in
if success {
print("Added to favorites")
}
}
PhotoKit предоставляет механизм наблюдения за изменениями медиатеки через протокол PHPhotoLibraryChangeObserver. При любых изменениях (создание, удаление, редактирование) вызывается метод photoLibraryDidChange с объектом PHChange.
PHChange содержит changeDetails для каждого типа запроса: PHFetchResultChangeDetails с removedIndexes, insertedIndexes, changedIndexes. Это позволяет применять изменения к UI с анимацией: performBatchUpdates с move, insert, delete для UICollectionView.
class PhotosViewController: UIViewController {
var fetchResult: PHFetchResult>PHAsset>?
override func viewDidLoad() {
super.viewDidLoad()
PHPhotoLibrary.shared().register(self)
}
deinit {
PHPhotoLibrary.shared().unregisterChangeObserver(self)
}
}
extension PhotosViewController: PHPhotoLibraryChangeObserver {
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let fetchResult,
let details = changeInstance.changeDetails(for: fetchResult)
else { return }
DispatchQueue.main.async {
self.fetchResult = details.fetchResultAfterChanges
// Применить изменения к collectionView
}
}
}
PhotoKit поддерживает редактирование медиа через механизм PHContentEditingInput и PHContentEditingOutput. Приложение запрашивает editingInput с исходными данными, применяет изменения и сохраняет результат через editingOutput. Фреймворк автоматически сохраняет оригинал, позволяя пользователю откатить изменения через сброс до оригинала.
RAW-фотографии (DNG, CR2, NEF) поддерживаются через PHAssetResourceManager, который предоставляет доступ к исходному RAW-файлу. Для обработки RAW рекомендуется использовать CoreImage с фильтром CIRAWFilter, который поддерживает настройку температуры, экспозиции и резкости. PhotoKit также поддерживает расширения редакторов через Photo Editing Extension (iOS) — приложение может быть вызвано из системного редактора для обработки выбранного фото или видео.
PhotoKit — мощный, но ресурсоёмкий фреймворк. Неправильное использование может приводить к тормозам при скролле и излишнему расходу памяти. Следуйте рекомендациям для оптимальной производительности.
PHLivePhoto — требует отдельного запроса через PHLivePhoto.request(with:targetSize:contentMode:options:resultHandler:). Не запрашивайте Live Photo для ячеек, где отображается только фото — используйте PHLivePhotoBadge для индикации.
Часто задаваемые вопросы
PhotoKit — современный фреймворк Apple для работы с медиатекой, представленный в iOS 8. В отличие от устаревшего AssetsLibrary, PhotoKit предоставляет объектную модель PHAsset, PHFetchResult с быстрым поиском, поддержку iCloud и Change Tracking для наблюдения за изменениями.
Вызовите PHPhotoLibrary.requestAuthorization(for: .readWrite) с обработкой в колбэке. После получения статуса .authorized можно выполнять запросы PHAsset.fetchAssets. Для записи требуется доступ .readWrite. Для только чтения — .addOnly.
Используйте PHImageManager.default().requestImage с параметрами: asset, targetSize, contentMode и PHImageRequestOptions. Асинхронный метод возвращает PHImageRequestID, позволяющий отменить запрос. Для коллекций используйте PHCachingImageManager с предзагрузкой.
Зарегистрируйте наблюдателя через PHPhotoLibrary.shared().register(self) и реализуйте протокол PHPhotoLibraryChangeObserver. В методе photoLibraryDidChange получите PHChange с changeDetails для каждого fetchResult и примените изменения к UI с анимацией.
В PHImageRequestOptions установите isNetworkAccessAllowed = true и progressHandler для отслеживания загрузки из iCloud. При быстром скролле отключайте сетевой доступ и загружайте только локальные версии, чтобы избежать задержек при скролле.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также