PhotoKit — What It Is, Key Concepts, and PHAsset

Author: IT Sectr Published: 2026-05-06 Reading time: 8 min

PhotoKit is an Apple framework for working with the media library on iOS and macOS, providing direct access to photos, videos, and Live Photos on the device. According to Apple’s documentation, the framework replaces the legacy AssetsLibrary and supports iCloud, albums, editing, and Change Tracking. PhotoKit provides a unified API for queries, caching, and media library changes with automatic synchronization via iCloud.

Key Takeaways

  • PhotoKit is an Apple framework for working with the system media library, providing access to photos, videos, Live Photos, and albums.
  • PHAsset is a data model representing a single media item (photo or video) with metadata: date, location, type.
  • PHFetchResult is a query result container with lazy loading and change notifications via PHPhotoLibraryChangeObserver.
  • PHImageManager is a manager for retrieving images with size, mode, and caching options via PHCachingImageManager.
  • PHPhotoLibrary is the entry point for performing changes: creating, deleting, and editing media objects.

What Is PhotoKit?

PhotoKit is an Apple framework (introduced in iOS 8, macOS 10.11) that provides an object-oriented API for working with the system media library. Unlike AssetsLibrary, PhotoKit treats the media library as a database: queries return PHAsset, PHCollection, and PHCollectionList objects representing the content and storage structure.

PhotoKit supports all media types: photos (JPEG, HEIF, RAW), videos (MOV, MP4), Live Photos, and burst shots. The framework automatically manages iCloud synchronization: if an image is stored in iCloud, PhotoKit requests it over the network and reports progress via PHImageRequestOptions.progressHandler.

A key feature of PhotoKit is the data model based on PHObject with a local identifier (localIdentifier) that remains stable between sessions. This allows you to save references to media objects and restore them after app restart without re-querying.

How PhotoKit Works: Data Model and Queries

PhotoKit is built on three levels: data model (PHObject), queries (PHFetchResult), and changes (PHPhotoLibrary.performChanges). The data model is hierarchical: PHAsset (photo/video) resides within PHAssetCollection (album), and albums are grouped into PHCollectionList (folder).

Performing Queries

Queries are executed via PHAsset.fetchAssets and PHAssetCollection.fetchAssetCollections. All fetch methods are synchronous and return PHFetchResult, which immediately executes the query against the media library database. PHFetchResult supports fast indexed access (object(at:)) and enumeration via enumerateObjects.

  • fetchAssets(with:options:) — query all media filtered by type, date, album
  • fetchAssetCollections(with:subtype:options:) — query albums and folders
  • fetchAssets(in:options:) — query media within a specific album

PHFetchOptions

PHFetchOptions is an object for configuring queries: sorting (sortDescriptors), predicate (predicate), including hidden and deleted media (includeHiddenAssets, includeAllBurstAssets). Fetch options allow filtering by media type: PHAssetMediaType.image, .video, .audio.

Core PhotoKit Classes

PhotoKit includes a set of classes for accessing, querying, and modifying the media library. Understanding each of them is essential for working effectively with the framework.

PHAsset

PHAsset is an immutable object representing a single media item. It contains metadata: mediaType, mediaSubtypes, creationDate, location, pixelWidth, pixelHeight, duration (for video), isFavorite, burstIdentifier. LocalIdentifier is a stable string key accessible even after app restart.

PHAssetCollection

PHAssetCollection is a group of media: system albums (Recents, Favorites, Selfies, Screenshots), user albums, or Moments (automatically grouped by time and place). Attributes: localizedTitle, assetCollectionType, assetCollectionSubtype, startDate, endDate.

PHCollectionList

PHCollectionList is a folder containing albums (PHAssetCollection) or other folders. It is rarely used, mainly for displaying hierarchy in the user interface.

PHImageManager and Caching

PhotoKit does not return UIImage directly from PHAsset — you need to request an image via PHImageManager. This ensures that the image is loaded with iCloud support, caching, and the required size.

ComponentPurposeFeature
PHImageManager.default()Standard manager for one-off requestsNo caching between requests
PHCachingImageManagerManager with preloading for collectionsstartCachingImages for smooth scrolling
PHImageRequestOptionsRequest settings: size, mode, deliverysynchronous, deliveryMode, progressHandler
PHImageRequestIDRequest identifier for cancellationcancelImageRequest(PHImageRequestID)

PHImageManager supports three delivery modes: opportunistic (first a reduced version, then full), highQualityFormat (full quality only), and fastFormat (fastest available version). For collections, always use PHCachingImageManager with image preloading for visible cells.

PhotoKit Usage Examples in Swift

PhotoKit is used for creating custom galleries, editors, and media applications. Let’s look at three key scenarios.

Fetching All Photos from the Media Library

PHAsset.fetchAssets with PHFetchOptions sorted by creation date is the basic query for building a custom photo gallery. PHFetchResult supports lazy loading and streaming access.

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 is a thread-safe container. Accessing objects by index via object(at:) does not block the UI, but requesting an image via PHImageManager should be done asynchronously.

Loading Images with Caching

PHCachingImageManager is a subclass of PHImageManager with startCachingImages and stopCachingImages methods for preloading. It is used in UICollectionView for smooth scrolling.

swift
let cachingManager = PHCachingImageManager()
let targetSize = CGSize(width: 200, height: 200)

// Preload for visible cells
cachingManager.startCachingImages(
    for: visibleAssets,
    targetSize: targetSize,
    contentMode: .aspectFill,
    options: nil
)

// Request image via PHImageRequestOptions with 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)")
}

Editing the Media Library: Adding Favorites

Changes to the media library are performed via PHPhotoLibrary.shared().performChanges inside a changeRequest block. All operations are batched and applied transactionally.

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

Changes and Observation via Change Tracking

PhotoKit provides a mechanism for observing media library changes through the PHPhotoLibraryChangeObserver protocol. When any changes occur (creation, deletion, editing), the photoLibraryDidChange method is called with a PHChange object.

PHChange contains changeDetails for each query type: PHFetchResultChangeDetails with removedIndexes, insertedIndexes, changedIndexes. This allows applying changes to the UI with animation: performBatchUpdates with move, insert, delete for 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
            // Apply changes to collectionView
        }
    }
}

Editing RAW and Extensions

PhotoKit supports media editing through the PHContentEditingInput and PHContentEditingOutput mechanism. The app requests editingInput with original data, applies changes, and saves the result via editingOutput. The framework automatically preserves the original, allowing users to revert changes by resetting to the original.

RAW photos (DNG, CR2, NEF) are supported via PHAssetResourceManager, which provides access to the original RAW file. For RAW processing, it is recommended to use CoreImage with the CIRAWFilter, which supports adjustment of temperature, exposure, and sharpness. PhotoKit also supports editor extensions via Photo Editing Extension (iOS) — an app can be invoked from the system editor to process a selected photo or video.

Optimizing PhotoKit Performance

PhotoKit is a powerful but resource-intensive framework. Improper use can lead to scroll lag and excessive memory consumption. Follow these recommendations for optimal performance.

  • Use PHCachingImageManager for collections — preloading images for visible +/-1 screen cells eliminates scroll lag
  • Set targetSize — never request PHImageManagerMaximumSize for thumbnails. Use a size equal to the cell’s physical size multiplied by the screen scale
  • Cancel requests on cell reuse — save PHImageRequestID and call cancelImageRequest in prepareForReuse
  • Limit iCloud requests — during fast scrolling, set isNetworkAccessAllowed = false and load iCloud photos only when stopped
  • Cache PHFetchResult — repeated fetchAssets with the same options return a new PHFetchResult. Save the result as a property and update it via Change Observer

PHLivePhoto requires a separate request via PHLivePhoto.request(with:targetSize:contentMode:options:resultHandler:). Do not request Live Photo for cells that display only photos — use PHLivePhotoBadge for indication.

Frequently Asked Questions

What Is PhotoKit and How Is It Different from AssetsLibrary?

PhotoKit is a modern Apple framework for working with the media library, introduced in iOS 8. Unlike the legacy AssetsLibrary, PhotoKit provides the PHAsset object model, PHFetchResult with fast search, iCloud support, and Change Tracking for observing changes.

How to Request Access to the Media Library via PhotoKit?

Call PHPhotoLibrary.requestAuthorization(for: .readWrite) with a callback handler. After receiving .authorized status, you can execute PHAsset.fetchAssets queries. Write access requires .readWrite permission. For read-only — .addOnly.

How to Get an Image from PHAsset?

Use PHImageManager.default().requestImage with parameters: asset, targetSize, contentMode, and PHImageRequestOptions. The asynchronous method returns PHImageRequestID, allowing you to cancel the request. For collections, use PHCachingImageManager with preloading.

How to Track Changes in the Media Library?

Register an observer via PHPhotoLibrary.shared().register(self) and implement the PHPhotoLibraryChangeObserver protocol. In the photoLibraryDidChange method, receive PHChange with changeDetails for each fetchResult and apply changes to the UI with animation.

How to Handle iCloud Photos in PhotoKit?

In PHImageRequestOptions, set isNetworkAccessAllowed = true and a progressHandler for tracking iCloud download progress. During fast scrolling, disable network access and load only local versions to avoid scroll delays.

Summary

  • PhotoKit is an Apple framework for working with the media library, replacing AssetsLibrary since iOS 8 and macOS 10.11.
  • PHAsset is the core data model with a local identifier, type, date, location, and size.
  • PHFetchResult performs synchronous queries to the storage and provides thread-safe access to results.
  • PHCachingImageManager with preloading ensures smooth scrolling in collections without delays.
  • Change Tracking via PHPhotoLibraryChangeObserver allows the UI to instantly react to media library changes.
  • iCloud synchronization is built into the framework: requesting an image automatically downloads it from iCloud with progress.
  • Optimization — proper targetSize, request cancellation, and iCloud limiting during scrolling are critical for performance.

We will develop a mobile application turnkey

IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.

Discuss the project

Read also