Mobile Development 13 min read

Mastering iOS 14 PHPicker: Access Limited Photos Without Permissions

This article explains how to correctly use the iOS 14 PHPicker API to let users select a limited set of photos without requesting full library permission, covering component basics, configuration, common pitfalls, proper data loading, handling special formats, and progress monitoring with Swift code examples.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Mastering iOS 14 PHPicker: Access Limited Photos Without Permissions

iOS 14 introduced a new privacy‑focused photo‑selection workflow called Limited Photo Library Access . When an app requests access, users can now choose to grant access to only selected photos. The system provides the PHPicker API, which lives in the PhotosUI framework rather than UIKit. This article walks through the complete lifecycle of using PHPicker correctly, from configuration to retrieving image or video data without requesting full library permission.

What is PHPicker?

PHPicker

consists of four main classes:

PHPickerViewController
PHPickerConfiguration
PHPickerFilter
PHPickerResult

When you present a PHPickerViewController, you provide a PHPickerConfiguration that specifies the selection limit, media types (images, live photos, videos), and a filter to restrict the allowed types.

Typical Mistake – Mixing PHPicker with PHAsset

Many tutorials mistakenly call PHAsset.fetchAssets after a limited‑access picker. In limited mode fetchAssets can only return assets the user has explicitly granted access to, so the call often returns an empty result and defeats the purpose of PHPicker. The correct approach is to use the NSItemProvider returned by the PHPickerResult delegate.

Correct Usage

Implement PHPickerViewControllerDelegate and handle the didFinishPicking callback:

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    picker.dismiss(animated: true)
    for result in results {
        let itemProvider = result.itemProvider
        // Determine the type and load the appropriate representation
    }
}

Use itemProvider.hasItemConformingToTypeIdentifier(_:) with UTType constants to differentiate images, videos, WebP, GIF, etc.

Loading Image Data

For images, the recommended method is loadDataRepresentation(forTypeIdentifier:completionHandler:), which returns Data. The data can be turned into a UIImage and fed into an EXIF‑parsing helper (e.g., the open‑source ExifData library) to extract metadata such as pixel dimensions, color model, and GIF flag.

itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, error in
    guard let data = data, error == nil else { return }
    let image = UIImage(data: data)
    // Use ExifData to read metadata
}

Loading Video Data

For videos, use loadFileRepresentation(forTypeIdentifier:completionHandler:) to obtain a temporary URL. From the URL you can create an AVAsset for playback or further processing.

itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in
    guard let url = url, error == nil else { return }
    let asset = AVAsset(url: url)
    // Process video asset
}

Handling Special Formats (WebP, GIF)

After confirming the item conforms to UTType.image, further checks with UTType.webP or UTType.gif let you branch to format‑specific handling code.

if itemProvider.hasItemConformingToTypeIdentifier(UTType.webP.identifier) {
    // WebP handling
} else if itemProvider.hasItemConformingToTypeIdentifier(UTType.gif.identifier) {
    // GIF handling
}

Monitoring Load Progress

When loading large resources, loadDataRepresentation returns an NSProgress object. Add an observer for the fractionCompleted key path to update a UI progress bar.

var progress: Progress?
progress = itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, error in
    // handle data
}
progress?.addObserver(self, forKeyPath: "fractionCompleted", options: [.new], context: nil)

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if keyPath == "fractionCompleted" {
        print("fractionCompleted = \(self.progress?.fractionCompleted ?? 0)")
    }
}

Summary of Best Practices

Use PHPicker for iOS 14+ to avoid requesting full photo‑library permission.

Configure PHPickerConfiguration with selectionLimit and filter to control how many items and which media types the user can pick.

Never call PHAsset.fetchAssets after a limited‑access picker; rely on the NSItemProvider returned by the delegate.

Load image data with loadDataRepresentation (returns Data) and video data with loadFileRepresentation (returns URL).

Use UTType to distinguish regular images, WebP, GIF, and movies, and apply format‑specific processing.

Extract EXIF metadata from the image Data using a helper such as the open‑source ExifData library.

Monitor large file loading with the returned NSProgress to provide user feedback.

By following these steps, developers can implement a privacy‑respectful photo‑selection flow that matches Apple’s design intent and delivers a smoother user experience.

PHPicker illustration
PHPicker illustration
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

iOSSwiftPhoto LibraryEXIFLimited AccessNSItemProviderPHPickerUTType
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.