Handle the Limited Photos Library in your app
Privacy & Security 进阶 20m

在应用中处理受限照片库

Handle the Limited Photos Library in your app

2020年6月25日

在 Apple 官方观看视频

一句话判断

iOS 14 新增了”仅选中的照片”权限——用户可以只给你看特定的几张照片,而不是整个相册。如果你的 App 请求相册权限,你必须处理这个新的授权状态。

这场 Session 讲了什么

这场 Session 介绍了 iOS 14 中 Photos 框架的重要隐私更新:Limited Photos Library(受限照片库)。在此之前,相册权限只有”允许”和”拒绝”两种状态。iOS 14 新增了第三种——“仅选中的照片”,用户可以精确选择哪些照片对你的 App 可见。

演讲者首先介绍了新的 PHAuthorizationStatus.limited 状态。当用户选择”仅选中的照片”时,你的 App 通过 PHAsset.fetchAssets 获取到的资产列表只包含用户选中的那些照片。你的 App 不会知道用户还有其他照片——从 API 的角度看,就像用户的相册里真的只有这几张照片一样。

Session 的核心部分讲解了如何适配这个新状态。关键 API 叆化包括:PHPickerViewController(新增的隐私友好的照片选择器,不需要相册权限就能使用)、PHPhotoLibrary.requestAuthorization 的更新(支持传入 .limited 参数),以及如何监听用户更改选中照片的范围。

演讲者还讨论了迁移策略——如何从旧的”全量访问”模式平滑迁移到支持 limited 状态的代码,以及如何在 UI 中告知用户他们只给了有限权限。

值得深挖的点

  • PHPickerViewController vs PHAssetFetchRequest:PHPickerViewController 是 Apple 推荐的照片选择方式——它不需要你的 App 获得任何相册权限。用户在 Picker 中选择照片后,你的 App 只能获得被选中的照片数据。这是一种”按需授权”的隐私模型,与”全量授权后自己筛选”的传统模型截然不同。对于只需要偶尔访问几张照片的 App 来说,PHPickerViewController 是更好的选择。
  • 数据一致性的处理:用户可能在你正在展示照片列表的时候更改了选中范围。你需要监听 PHPhotoLibraryChangeObserver 来处理这种场景——如果用户取消了某张照片的授权,你的 App 需要从展示列表中移除它,而不是尝试访问已被拒绝的资源。

代码片段

// 请求相册权限并处理 limited 状态
import Photos

func requestPhotoPermission() {
    PHPhotoLibrary.requestAuthorization(for: .readWrite) { status in
        DispatchQueue.main.async {
            switch status {
            case .authorized:
                // 完整相册访问
                self.loadAllPhotos()
            case .limited:
                // 只能访问用户选中的照片
                self.loadLimitedPhotos()
            case .denied, .restricted:
                // 无权限,使用 PHPicker 作为替代
                self.showPermissionDenied()
            default:
                break
            }
        }
    }
}
// 使用 PHPickerViewController(无需相册权限)
import PhotosUI

func showPhotoPicker() {
    var config = PHPickerConfiguration()
    config.selectionLimit = 5  // 最多选择 5 张
    config.filter = .images    // 只显示图片

    let picker = PHPickerViewController(configuration: config)
    picker.delegate = self
    present(picker, animated: true)
}

// 处理选择结果
func picker(
    _ picker: PHPickerViewController,
    didFinishPicking results: [PHPickerResult]
) {
    picker.dismiss(animated: true)

    for result in results {
        // 获取选中的图片
        let provider = result.itemProvider
        if provider.canLoadObject(ofClass: UIImage.self) {
            provider.loadObject(ofClass: UIImage.self) { image, error in
                if let image = image as? UIImage {
                    // 使用选中的图片
                    self.processSelectedImage(image)
                }
            }
        }
    }
}
// 监听选中照片范围的变化
class PhotoManager: NSObject, PHPhotoLibraryChangeObserver {
    func registerForChanges() {
        PHPhotoLibrary.shared().register(self)
    }

    func photoLibraryDidChange(_ changeInstance: PHChange) {
        DispatchQueue.main.async {
            // 用户可能更改了"仅选中的照片"范围
            // 重新加载照片列表
            self.reloadPhotoCollection()
        }
    }

    // 引导用户管理选中照片
    func showLimitedLibraryPicker() {
        // iOS 14 新增:让用户重新选择哪些照片可见
        let viewController = PHPhotoLibrary.shared()
            .limitedLibraryPickerViewController()
        viewController.delegate = self
        present(viewController, animated: true)
    }
}

最佳实践

  • 如果只需要偶尔选照片,使用 PHPickerViewController 而非请求相册权限
  • 正确处理 .limited 状态,在 UI 中清晰告知用户当前可见的照片范围
  • 监听 PHPhotoLibraryChangeObserver,及时响应用户对选中范围的更改
  • 不要因为用户给了 limited 权限就反复弹窗要求 full access
  • 在 App 的设置页面提供”管理照片权限”入口,方便用户随时调整

还有什么值得关注

  • PHPicker 后来在 iOS 16 中增加了对 Live Photo 和视频编辑的支持
  • iOS 14 的隐私改进还包括” approximate location”(模糊定位),同样是”给最少够用的权限”理念
  • 搭配 “What’s new in Privacy” 一起看,可以全面了解 iOS 14 的隐私框架变化
WWDC 2020