专栏首页ios技术安装iOS14中的PHPicker
原创

iOS14中的PHPicker

PHPicker

iOS 14 中系统新增了一个图片选择器 PHPicker,官方建议使用 PHPicker 来替代原有的 API 进行图片选择,下面我们来看看 PHPicker 的优点:

  • 支持多选
  • 支持搜索
  • 独立的进程
  • 内置隐私
    • 不需要直接访问用户相册
    • 不会弹出访问相册提示
    • 仅提供用户选择的照片和视频(App 无法获取其他照片)

如何调用 PHPicker

我们先来看下 PHPicker 的流程图,首先声明 PHPickerConfiguration,进行配置,再传给 PHPickerViewController,完成调用环节,代码如下:

var config = PHPickerConfiguration()
// 可选择的资源数量,0表示不设限制,默认为1
config.selectionLimit = 0
// 可选择的资源类型
// 只显示图片(注:images 包含 livePhotos)
config.filter = .images
// 显示 Live Photos 和视频(注:livePhotos 不包含 images)
config.filter = .any(of: [.livePhotos, .videos])
// 如果要获取视频,最好设置该属性,避免系统对视频进行转码
config.preferredAssetRepresentationMode = .current

let picker = PHPickerViewController(configuration: config)
picker.delegate = self
present(picker, animated: true, completion: nil)复制代码

处理 PHPicker 的回调

PHPicker 的代理方法只有一个,声明如下:

@available(iOS 14, *)
public protocol PHPickerViewControllerDelegate : AnyObject {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
}复制代码

注意: 取消选择也会触发代理方法,会返回空的 results

如何获取照片

PHPicker 获取图片的方法还是比较简单的,代码如下:

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // 首先需要 dismiss picker
    picker.dismiss(animated: true, completion: nil)
    for result in results {
        // 判断类型是否为 UIImage
        if result.itemProvider.canLoadObject(ofClass: UIImage.self) {
            // 确认类型后,调用 loadObject 方法获取图片
            result.itemProvider.loadObject(ofClass: UIImage.self) { (data, error) in
                // 回调结果是在异步线程,展示时需要切换到主线程
                if let image = data as? UIImage {
                    DispatchQueue.main.async {
                        self.showImage(image)
                    }
                }
            }
        }
    }
}复制代码

如何获取视频

其他文章中都没有介绍 PHPicker 如何获取视频,其实获取视频的方法在官方的 Demo 以及视频中都没有介绍,这也是我迟迟没有写文章的原因,因为之前我也不知道怎么获取,那么下面让我们一起来看下怎么获取视频。

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // 首先需要 dismiss picker
    picker.dismiss(animated: true, completion: nil)
    for result in results {
        if result.itemProvider.canLoadObject(ofClass: UIImage.self) {
            // 判断类型是否为 UIImage
            ...
        } else {
            // 类型为 Video
            // 调用 loadFileRepresentation 方法获取视频的 url
            // 这里 Type Identifier 我们用 UTType.movie.identifier (“public.movie”) 这个 UTI 可以获取所有格式的视频
            result.itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { (url, error) in
                if let error = error {
                    print(error)
                    return
                }
                // 系统会将视频文件存放到 tmp 文件夹下
                // 我们必须在这个回调结束前,将视频拷贝出去,一旦回调结束,系统就会把视频删掉
                // 所以一定要确定拷贝结束后,再切换到主线程做 UI 操作
                // 另外不用担心视频过大而导致拷贝的时间很久,系统将创建一个 APFS 的克隆项,因此拷贝的速度会非常快
                guard let url = url else { return }
                let fileName = "\(Int(Date().timeIntervalSince1970)).\(url.pathExtension)"
                let newUrl = URL(fileURLWithPath: NSTemporaryDirectory() + fileName)
                try? FileManager.default.copyItem(at: url, to: newUrl)
                DispatchQueue.main.async {
                    self.playVideo(newUrl)
                }
            }
        }
    }
}复制代码

注意: 如果你遇到了部分资源可以加载,而部分资源无法加载的话,那么有可能是设备没有连接到 iCloud,只能加载本地资源,而无法加载 iCould 上的资源。

被废弃的 API

有新的 API 出现,也会有一些 API 被废弃,在 UIImagePickerController 中有三个 sourceType,现在有两个被废弃,只留下 camera

public enum SourceType : Int {
    @available(iOS, introduced: 2, deprecated: 100000, message: "Will be removed in a future release, use PHPicker.")
    case photoLibrary = 0
    case camera = 1
    @available(iOS, introduced: 2, deprecated: 100000, message: "Will be removed in a future release, use PHPicker.")
    case savedPhotosAlbum = 2
}复制代码

另外 AssetsLibrary 早在几年前被废弃,如果还在使用 AssetsLibrary 请尽快使用新的 API。

PHPicker 的缺点

为什么不推荐使用 PHPicker,虽然说 PHPicker 有一些优点,但同时也有一些缺点:

  • 加载 iCloud 资源时没有进度回调
  • 不支持图片编辑(比如选择头像要将图片裁剪成正方形)

有没有其他的解决方案?

有的,如果你不能接受 PHPicker 的缺点,同时又想保护用户的隐私,目前有 Picker、Editor、Capture 三个模块,支持图片/视频选择、编辑、拍摄功能,支持 SPM、CocoaPods 方式引入。

新增权限

iOS 14 中相册新增了一个 “Limited Photos Library” 模式,在授权时多了一个 “选择照片” 的选项。点击之后系统会弹出 PHPickerController 用户可以选择指定的照片让 App 读取。

当用户选择了 limited 模式后,系统将在 App 每次启动后首次触发相册时弹出提示,允许用户修改需要授权给 App 的照片。iOS开发交流技术群:[563513413](https://jq.qq.com/?_wv=1027&k=lzJejkSl),不管你是大牛还是小白都欢迎入驻

当然这个弹窗是可以关闭的,如果你希望手动控制 PHPickerController 弹出的时机也是有办法的。

我们需要在 Info.plist 中添加 PHPhotoLibraryPreventAutomaticLimitedAccessAlert 字段,并设置为 YES,设置后系统将不再弹出访问提示。

然后我们可以在合适的时机调用以下这个 API 来推出 PHPickerController

let viewController = self
PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: viewController)复制代码

我们可以看到,当用户选择 limited 模式后,底部出现了一段提示:“无法查看相册全部照片,点击选择更多照片”。当点击这个提示后,将会推出 PHPickerController,此时用户可以修改授权给 App 的照片。同时我们会监听相册的变化,当用户修改授权的照片后,会立即刷新相册,用户可以继续进行选择照片的流程。

监听相册变化

配合手动调用 PHPickerController,我们还需要监听用户添加/删除了哪些照片。

注意: 这组 API 并不是新出的,从 iOS 8 开始就支持了。

let viewController = self
// 开始监听
PHPhotoLibrary.shared().register(viewController) 
// 结束监听
PHPhotoLibrary.shared().unregisterChangeObserver(viewController)复制代码

处理监听回调:

/// 回调方法
func photoLibraryDidChange(_ changeInstance: PHChange) {
    // Your code
}复制代码

由于这是一组旧的 API,所以就不介绍细节了(比如判断是新增还是删除),感兴趣的朋友可以去了解一下。

新增的 API

PHAccessLevel

在 iOS 14 中新增了权限等级枚举 PHAccessLevel,有两个 case,分别是 “只读” 和 “读写”。

public enum PHAccessLevel : Int {
    case addOnly = 1
    case readWrite = 2
}复制代码

对应新增了一组获取/查看权限的 API:

let level: PHAccessLevel = .readWrite
// 获取权限
PHPhotoLibrary.requestAuthorization(for: level) { status in
  // Your code
}
// 查看权限
let status: PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus(for: level)复制代码

PHAuthorizationStatus

PHAuthorizationStatus 新增了一个 case limited

public enum PHAuthorizationStatus : Int {
    case notDetermined = 0
    case restricted = 1
    case denied = 2
    case authorized = 3
    @available(iOS 14, *)
    case limited = 4
}复制代码

当用户在授权时选择了 “选择照片” 的选项时:

  • 使用新 API 将会返回 limited case
  • 使用旧 API 将会返回 authorized case

注意: limited case 仅在 PHAccessLevel = .readWrite 时会返回。

总结

新出的 PHPicker 个人觉得一般,如果对 Picker 要求不多的朋友可以考虑使用。然后是新出的 “Limited Photos Library” 模式,这个非常棒,如果有自定义 Picker 的朋友建议跟进一下。

原创声明,本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

登录 后参与评论
0 条评论

相关文章

  • 为什么不推荐使用PHPicker

    iOS 14 中系统新增了一个图片选择器 PHPicker,官方建议使用 PHPicker 来替代原有的 API 进行图片选择,下面我们来看看 PHPicker...

    ios-lan
  • iOS14新功能 - 特定声音的识别和监听

    Apple于2020年WWDC发布iOS14,其中一个看起来很小却非常重要的一个功能是声音识别(sound recognition)。

    用户6026865
  • iOS14 - 为听力障碍人士打造的声音识别功能

    从应用角度,对于很多人来说可能是锦上添花的功能,但对于听力障碍人士来说,相当于拥有了一双可以感知环境声音的耳朵。尽管所支持的声音感知还比较有限,但诸如高静音,孩...

    用户6026865
  • 【iOS】记录iOS14以及xcode12 遇到的问题

    问题描述: 内购完成会,会受到以下回调,一般我们会通过payment的applicationusername用于关联我们的orderId等信息,但是在iOS1...

    MapleYe
  • 逐渐安卓化会是ios的归宿吗

    近日的苹果发布会虽然没等到iphone12,但ios14还是如期而至了。似乎是预示着这个版本的重大变革,ios14对新系统的定义就是“重塑iphone体验”。

    TestOps
  • iOS14适配之【使用AppTrackingTransparency以请求用户授权获取IDFA信息】

    iOS14 To use the AppTrackingTransparency framework

    公众号iOS逆向
  • iOS14.5.1适配:使用AppTrackingTransparency以请求用户授权获取IDFA信息【修订版】

    在 iOS13 及以前,系统会默认为用户开启允许追踪设置,我们可以简单的通过代码来获取到用户的 IDFA 标识符。

    公众号iOS逆向
  • iOS 14 egret H5游戏卡顿问题分析和部分解决办法

    测试1: 简单demo,使用egret引擎显示3000个图(都是同一个100*100 png 纹理),逐帧做旋转。(博客园视频播放可能有问题,视频地址:http...

    用户1258909
  • iOS14适配汇总:【1、隐私权限相关:定位、相册、IDFA 2、KVC相关3、UIView相关;4、网络相关】

    公众号iOS逆向
  • iOS14.2 beta3怎么样?如何下载iOS14描述文件来升级

    iPhone12正式发布后,苹果也于今日凌晨面向开发者推送了iOS 14.2 Beta3,更新包大小为628M左右,版本号 18B5072f,主要是以修复bug...

    conanma
  • iOS14 Beta4崩溃修改

    升级iOS 14Beta4后,有用户反馈使用我们APP时会崩溃,有登录的、查看详情的,都会出现崩溃。我们查看Bugly数据也发现崩溃率上升了0.02%,直接超出...

    莫空9081
  • 【周末水文】我的iPhone7升级到了iOS14后,又可以再战两年了

    苹果在9月17号推送了iOS14正式版,我在当天早上冒死(本人手机iphone7)升级到了iOS14。

    Lvshen
  • iOS14来啦!你们准备好了吗?

    2020年6月23日,苹果举办了有史以来首次线上全球开发者大会(WWDC 2020)。本次主题演讲没有现场观众、欢呼和掌声,但如约推出了iOS14。根据官方给出...

    用户5521279
  • 升级ios14 Xcode真机调试启动非常慢的问题解决

    赵哥窟
  • iOS14 定位适配:1、向用户申请临时开启一次精确位置权限的方案2、高德定位SDK适配

    iOS14新增了 精确定位 和 模糊定位 的概念,用户可以手动选择,模糊定位的误差约 500m 。可以根据实际功能判断是否可以接受用户选择模糊定位。

    公众号iOS逆向
  • 苹果进入下一个十年!抛弃英特尔,WWDC官宣将Mac迁移至自研芯片,首批年底上市

    就在刚刚,面对空无一人的Apple Park观众席,苹果CEO库克和以Memoji的形象出现在屏幕上开发者们一起,见证了他口中的这个“历史性的时刻”。

    大数据文摘
  • iOS14适配一查找哪些SDK使用剪切板

    iOS14公测版发出之后,我们app出现了从后台唤起会弹出 读取剪切板的 提示,安全要求要赶紧查,全局搜索了我们APP,发现并没有读取剪切板的代码,比窦娥还冤,...

    莫空9081

扫码关注腾讯云开发者

领取腾讯云代金券