iOS 系统提供的媒体资源选择器(PHPickerViewController)

简介

在前面的博客中我们已经介绍了一个系统为我们提供的媒体选择器UIImagePickerController,它的功能很强大,但是唯一的不足就是只能选取单个媒体资源,而PHPickerViewController恰恰弥补了这一空缺。

PHPickerViewController是iOS 14及更高版本中引入的一个现代化媒体选择器,旨在替代UIImagePickerController。它不仅提供了更灵活的媒体选择功能,还拥有更现代的用户界面。PHPickerViewController允许用户在一次选择操作中选择多个图片和视频,并且可以对选择的媒体类型进行更加细致的控制,例如仅选择图片、视频或Live Photos等。此外,PHPickerViewController不再需要用户授予应用完整的照片库访问权限,只需有限的选择访问权限,从而提高了用户隐私。

在本篇博客中,我们将详细介绍如何使用PHPickerViewController来实现多媒体选择功能,并展示其在实际应用中的优势和使用场景。

基本用法

  • 导入PhotosUI框架
Swift 复制代码
import PhotosUI
  • 初始化和配置PHPickerViewController
Swift 复制代码
var configuration = PHPickerConfiguration()
configuration.selectionLimit = 9 // 可选项,限制选择的媒体数量
configuration.filter = .images // 过滤选项,可以选择.images, .videos, 或 .any
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true, completion: nil)
  • 实现代理方法,获取用户选择媒体资源
Swift 复制代码
extension YourViewController: PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true, completion: nil)
        for result in results {
            result.itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in
                if let image = object as? UIImage {
                    DispatchQueue.main.async {
                        // 使用选择的图像
                    }
                }
            }
        }
    }
}

进阶配置

PHPickerViewController本身并没有提供什么配置的接口或者是属性,因为它的配置信息全都交给了configuration属性。

PHPickerConfiguration主要用于定制媒体选择器的行为和外观,下面我逐个来介绍一下:

  • **selectionLimit:**Int类型,设置用户可以选择媒体的最大数量,当设置为0时表示没有任何限制。
Swift 复制代码
configuration.selectionLimit = 5 // 允许选择最多5个媒体
  • **filter:**PHPickerFilter类型,设置允许选择的媒体类型,比如.images,.vides.或者.any。
Swift 复制代码
configuration.filter = .images // 只允许选择图片
configuration.filter = .any // 允许选择图片和视频
  • preferredAssetRepresentationMode: PHPickerConfiguration.AssetRepresentationMode,可以选择.automatic,.current或者.compatible,它决定了在选择媒体时应该使用的资源表示形式,在处理媒体文件的质量和兼容性方面非常有用。通常我们会选择.automatic,它通常是指设备的原始表示形式。
Swift 复制代码
configuration.preferredAssetRepresentationMode = .automatic
  • preselectedAssetIdentifiers: [String]类型,它主要用于初始化时显示你已经选择的媒体资源。
Swift 复制代码
 // 设置之前选中的标识符
        if #available(iOS 15.0, *) {
            configuration.preselectedAssetIdentifiers = previouslySelectedIdentifiers
        }
  • photoLibrary: PHPhotoLibrary,用于获取执行相册的媒体资源,默认情况下使用PHPhotoLibrary.shared()
Swift 复制代码
configuration.photoLibrary = PHPhotoLibrary.shared()
  • selection: Selection,用来指定用户选择媒体资源时的行为,有如下选项:.default,.ordered或者.unordered。
Swift 复制代码
configuration.selection = .ordered // 选中的媒体按顺序排列

使用示例

对于上面的场景,如果需要一次性选择多张照片(最多可选9张),使用PHPickerViewController是非常合适的选择。

首先我们来设置一些基本属性,比如可选资源最大个数,已选资源列表等等:

Swift 复制代码
    /// 最大数量
    private let maxCount = 9
    /// 已选结果
    private var selectedResults = [PHAlbumModel]()

其中PHAblbuModel是我们自定义数据模型,我们只需要图片资源和资源标识这两个数据,代码如下:

Swift 复制代码
class PHAlbumModel: NSObject {
    /// 图片
    var image:UIImage?
    /// 标识
    var identifier:String?
}

接下来我们来实现列表中的第一个元素的事件,显示多媒体资源选择视图控制器,代码如下:

Swift 复制代码
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if indexPath.row == 0 {
            // 选择图片
            showAlbum()
        }
    }
Swift 复制代码
    @objc func showAlbum() {
        if self.selectedResults.count >= maxCount {
            print("已经达到最大选择数量")
            return
        }
        var configuration = PHPickerConfiguration()
        // 资源类型
        configuration.filter = .images
        // 最大数量
        configuration.selectionLimit = maxCount - self.selectedResults.count + 1
        configuration.selection = .ordered
        // 预选资源
        var preselectedAssetIdentifiers = [String]()
        for model in selectedResults {
            if let identifier = model.identifier , identifier != "" {
                preselectedAssetIdentifiers.append(identifier)
            }
        }
        configuration.preselectedAssetIdentifiers = preselectedAssetIdentifiers
        let mediaPikcerViewController = PHPickerViewController(configuration: configuration)
        mediaPikcerViewController.delegate = self
        present(mediaPikcerViewController, animated: true, completion: nil)
        
    }

在上面的代码中:

我们过滤了资源的类型,只需要图片类型的媒体资源。

设置了资源的最大数量为,为最大数量减去已经选择的媒体数量。

设置了选中资源的显示顺序。

并且也设置了我们当前已经选择的媒体资源。

接下来来看一下代理方法的实现:

Swift 复制代码
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true, completion: nil)
        for result in results {
            let itemProvider = result.itemProvider
            if itemProvider.canLoadObject(ofClass: UIImage.self) {
                itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in
                    if let image = image as? UIImage {
                        let model = PHAlbumModel()
                        print("获取到图片 \(result.assetIdentifier)")
                        model.image = image
                        model.identifier = result.assetIdentifier
                        self?.selectedResults.append(model)
                        DispatchQueue.main.async {
                            self?.collectionView.reloadData()
                        }
                    }
                }
            }
        }
    }

获取到媒体资源之后,根据所需数据构建了我们自己的数据模型,并且添加到了已选择资源的列表中,回到主线程进行刷线列表。

结语

在本文中,我们详细探讨了 PHPickerViewController,一个用于选择照片和视频的强大工具。通过比较它与 UIImagePickerController 的不同,我们看到了 PHPickerViewController 的优势,特别是在支持多选和灵活配置方面。

PHPickerViewController 不仅简化了用户选择媒体的过程,还提供了更好的用户体验。尽管它不支持拍照或录像功能,但其多选能力和对不同媒体类型的支持,使其在许多应用场景中成为理想选择。通过合适的配置和管理选项,你可以充分利用这个工具,提升应用的功能和用户体验。

希望这篇文章能帮助你更好地理解和应用 PHPickerViewController。如有任何疑问或需要进一步讨论,请随时与我联系。感谢你的阅读和支持!

相关推荐
卜锦元2 小时前
音视频媒体服务领域中三种架构方式的定义与区别(Mesh、MCU、SFU)
架构·音视频·媒体
蚁巡信息巡查系统1 天前
自媒体内容安全审核指引怎么写,有哪些内容?
安全·信息可视化·媒体·内容运营
卜锦元2 天前
Mediasoup的SFU媒体服务转发中心详解(与传统SFU的区别)
音视频·webrtc·媒体
flex88884 天前
一款专为媒体爱好者设计的跨平台客户端软件,整合 Jellyfin、Emby、CMS 、webdav和IPTV媒体服务
媒体
Swift社区6 天前
iOS 基于 Foundation Model 构建媒体流
ios·iphone·swift·媒体
我希望的一路生花6 天前
告别文件混乱!Adobe Bridge 2026 全媒体可视化管理,让设计流程更顺畅
adobe·媒体
点金石游戏出海7 天前
每周资讯 | 印度数字媒体与娱乐市场在2025财年达93亿美;《崩坏:星穹铁道》新版本登顶iOS畅销榜首
游戏·娱乐·媒体·游戏资讯·崩坏星穹铁道
yingxiao8888 天前
挖掘百亿“数字热土”!解读印度游戏与媒体娱乐的高速增长
游戏·娱乐·媒体
十五年专注C++开发11 天前
Qt-VLC: 一个集成VLC的开源跨平台媒体播放库
开发语言·qt·媒体·libvlc·vlc-qt
present122714 天前
一段音频/视频分离成人声与伴奏,Windows + Anaconda 快速跑通 Spleeter(离线可用)
windows·职场和发展·ffmpeg·音视频·娱乐·媒体