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.
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?
PHPickerconsists of four main classes:
PHPickerViewController PHPickerConfiguration PHPickerFilter PHPickerResultWhen 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
