PhotoKit — что это, ключевые понятия и PHAsset

Автор: IT Sectr Опубликовано: 2026-05-06 Время чтения: 8 мин

PhotoKit — это фреймворк Apple для работы с медиатекой на iOS и macOS, предоставляющий прямой доступ к фото, видео и Live Photos на устройстве. По данным документации Apple, фреймворк заменяет устаревший AssetsLibrary и поддерживает iCloud, альбомы, редактирование и Change Tracking. PhotoKit обеспечивает единый API для запросов, кэширования и изменений медиатеки с автоматической синхронизацией через iCloud.

Главное

  • PhotoKit — фреймворк Apple для работы с системной медиатекой, предоставляющий доступ к фото, видео, Live Photos и альбомам.
  • PHAsset — модель данных, представляющая одно медиа-содержимое (фото или видео) с метаданными: дата, местоположение, тип.
  • PHFetchResult — контейнер результатов запроса с потоковой загрузкой и уведомлениями об изменениях через PHPhotoLibraryChangeObserver.
  • PHImageManager — менеджер для получения изображений с опциями размера, режима и кэширования через PHCachingImageManager.
  • PHPhotoLibrary — точка входа для выполнения изменений: создание, удаление и редактирование медиа-объектов.

Что такое PhotoKit?

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: модель данных и запросы

PhotoKit построен на трёх уровнях: модели данных (PHObject), запросов (PHFetchResult) и изменений (PHPhotoLibrary.performChanges). Модель данных иерархическая: PHAsset (фото/видео) находится внутри PHAssetCollection (альбом), альбомы группируются в PHCollectionList (папка).

Выполнение запросов

Запросы выполняются через PHAsset.fetchAssets и PHAssetCollection.fetchAssetCollections. Все методы fetch — синхронные и возвращают PHFetchResult, объект которого сразу выполняет запрос к базе данных медиатеки. PHFetchResult поддерживает быстрый доступ по индексу (object(at:)) и перечисление через enumerateObjects.

  • fetchAssets(with:options:) — запрос всех медиа с фильтрацией по типу, дате, альбому
  • fetchAssetCollections(with:subtype:options:) — запрос альбомов и папок
  • fetchAssets(in:options:) — запрос медиа внутри конкретного альбома

PHFetchOptions

PHFetchOptions — объект для конфигурации запроса: сортировка (sortDescriptors), предикат (predicate), включение скрытых и удалённых медиа (includeHiddenAssets, includeAllBurstAssets). Фетч-опции позволяют фильтровать по типу медиа: PHAssetMediaType.image, .video, .audio.

Основные классы PhotoKit

PhotoKit включает набор классов для доступа, запросов и изменения медиатеки. Понимание каждого из них необходимо для эффективной работы с фреймворком.

PHAsset

PHAsset — неизменяемый объект, представляющий одно медиа-содержимое. Содержит метаданные: mediaType, mediaSubtypes, creationDate, location, pixelWidth, pixelHeight, duration (для видео), isFavorite, burstIdentifier. LocalIdentifier — стабильный строковый ключ, доступный даже после перезапуска приложения.

PHAssetCollection

PHAssetCollection — группа медиа: системные альбомы (Recents, Favorites, Selfies, Screenshots), пользовательские альбомы или Moments (автоматически сгруппированные по времени и месту). Атрибуты: localizedTitle, assetCollectionType, assetCollectionSubtype, startDate, endDate.

PHCollectionList

PHCollectionList — папка, содержащая альбомы (PHAssetCollection) или другие папки. Используется редко, в основном для отображения иерархии в пользовательском интерфейсе.

PHImageManager и кэширование

PhotoKit не возвращает UIImage напрямую из PHAsset — нужно запросить изображение через PHImageManager. Это гарантирует, что изображение загружается с учётом iCloud, кэширования и требуемого размера.

КомпонентНазначениеОсобенность
PHImageManager.default()Стандартный менеджер для разовых запросовНет кэширования между запросами
PHCachingImageManagerМенеджер с предзагрузкой для коллекцийstartCachingImages для плавного скролла
PHImageRequestOptionsНастройки запроса: размер, режим, доставкаsynchronous, deliveryMode, progressHandler
PHImageRequestIDИдентификатор запроса для отменыcancelImageRequest(PHImageRequestID)

PHImageManager поддерживает три режима доставки: opportunistic (сначала уменьшенная версия, затем полная), highQualityFormat (только полное качество) и fastFormat (самая быстрая доступная версия). Для коллекций всегда используйте PHCachingImageManager с предзагрузкой изображений для видимых ячеек.

Примеры использования PhotoKit на Swift

PhotoKit используется для создания пользовательских галерей, редакторов и приложений для работы с медиа. Рассмотрим три ключевых сценария.

Запрос всех фотографий из медиатеки

PHAsset.fetchAssets с PHFetchOptions и сортировкой по дате создания — базовый запрос для построения пользовательской фотогалереи. PHFetchResult поддерживает lazy-loading и потоковый доступ.

swift
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 для плавного скролла.

swift
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. Все операции батчатся и применяются транзакционно.

swift
PHPhotoLibrary.shared().performChanges {
    let changeRequest = PHAssetChangeRequest(for: asset)
    changeRequest.isFavorite = .true
} completionHandler: { success, error in
    if success {
        print("Added to favorites")
    }
}

Изменения и наблюдение через Change Tracking

PhotoKit предоставляет механизм наблюдения за изменениями медиатеки через протокол PHPhotoLibraryChangeObserver. При любых изменениях (создание, удаление, редактирование) вызывается метод photoLibraryDidChange с объектом PHChange.

PHChange содержит changeDetails для каждого типа запроса: PHFetchResultChangeDetails с removedIndexes, insertedIndexes, changedIndexes. Это позволяет применять изменения к UI с анимацией: performBatchUpdates с move, insert, delete для UICollectionView.

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

Редактирование RAW и расширения

PhotoKit поддерживает редактирование медиа через механизм PHContentEditingInput и PHContentEditingOutput. Приложение запрашивает editingInput с исходными данными, применяет изменения и сохраняет результат через editingOutput. Фреймворк автоматически сохраняет оригинал, позволяя пользователю откатить изменения через сброс до оригинала.

RAW-фотографии (DNG, CR2, NEF) поддерживаются через PHAssetResourceManager, который предоставляет доступ к исходному RAW-файлу. Для обработки RAW рекомендуется использовать CoreImage с фильтром CIRAWFilter, который поддерживает настройку температуры, экспозиции и резкости. PhotoKit также поддерживает расширения редакторов через Photo Editing Extension (iOS) — приложение может быть вызвано из системного редактора для обработки выбранного фото или видео.

Оптимизация работы с PhotoKit

PhotoKit — мощный, но ресурсоёмкий фреймворк. Неправильное использование может приводить к тормозам при скролле и излишнему расходу памяти. Следуйте рекомендациям для оптимальной производительности.

  • Используйте PHCachingImageManager для коллекций — предзагрузка изображений для видимых +-1 экран ячеек устраняет задержки при скролле
  • Задавайте targetSize — никогда не запрашивайте PHImageManagerMaximumSize для миниатюр. Используйте размер, равный физическому размеру ячейки, умноженный на scale экрана
  • Отменяйте запросы при переиспользовании ячейки — сохраняйте PHImageRequestID и вызывайте cancelImageRequest в prepareForReuse
  • Ограничьте iCloud-запросы — при быстром скролле установите isNetworkAccessAllowed = false и загружайте iCloud-фото только при остановке
  • Кэшируйте PHFetchResult — повторные fetchAssets с теми же опциями возвращают новый PHFetchResult. Сохраняйте результат в свойстве и обновляйте через Change Observer

PHLivePhoto — требует отдельного запроса через PHLivePhoto.request(with:targetSize:contentMode:options:resultHandler:). Не запрашивайте Live Photo для ячеек, где отображается только фото — используйте PHLivePhotoBadge для индикации.

Часто задаваемые вопросы

Что такое PhotoKit и чем он отличается от AssetsLibrary?

PhotoKit — современный фреймворк Apple для работы с медиатекой, представленный в iOS 8. В отличие от устаревшего AssetsLibrary, PhotoKit предоставляет объектную модель PHAsset, PHFetchResult с быстрым поиском, поддержку iCloud и Change Tracking для наблюдения за изменениями.

Как запросить доступ к медиатеке через PhotoKit?

Вызовите PHPhotoLibrary.requestAuthorization(for: .readWrite) с обработкой в колбэке. После получения статуса .authorized можно выполнять запросы PHAsset.fetchAssets. Для записи требуется доступ .readWrite. Для только чтения — .addOnly.

Как получить изображение из PHAsset?

Используйте PHImageManager.default().requestImage с параметрами: asset, targetSize, contentMode и PHImageRequestOptions. Асинхронный метод возвращает PHImageRequestID, позволяющий отменить запрос. Для коллекций используйте PHCachingImageManager с предзагрузкой.

Как отслеживать изменения в медиатеке?

Зарегистрируйте наблюдателя через PHPhotoLibrary.shared().register(self) и реализуйте протокол PHPhotoLibraryChangeObserver. В методе photoLibraryDidChange получите PHChange с changeDetails для каждого fetchResult и примените изменения к UI с анимацией.

Как обрабатывать iCloud-фото в PhotoKit?

В PHImageRequestOptions установите isNetworkAccessAllowed = true и progressHandler для отслеживания загрузки из iCloud. При быстром скролле отключайте сетевой доступ и загружайте только локальные версии, чтобы избежать задержек при скролле.

Итоги

  • PhotoKit — фреймворк Apple для работы с медиатекой, заменивший AssetsLibrary с iOS 8 и macOS 10.11.
  • PHAsset — основная модель данных с локальным идентификатором, типом, датой, местоположением и размером.
  • PHFetchResult выполняет синхронный запрос к хранилищу и предоставляет потокобезопасный доступ к результатам.
  • PHCachingImageManager с предзагрузкой обеспечивает плавный скролл в коллекциях без задержек.
  • Change Tracking через PHPhotoLibraryChangeObserver позволяет UI мгновенно реагировать на изменения медиатеки.
  • iCloud-синхронизация встроена в фреймворк: запрос изображения автоматически загружает его из iCloud с прогрессом.
  • Оптимизация — правильный targetSize, отмена запросов и ограничение iCloud при скролле критичны для производительности.

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также