相册处理的新框架.
类作用介绍
-
PHPhotoLibrary
- 对相册内容进行修改(添加图片, 删除图片, 新建相册等)
- 监听相册内容的变化
-
PHObject
- 基类, 只有一个属性localIdentifier(只读的资源的唯一标示符)
- 相册里的所有资源对象(相片, 相册, 等)都继承自他
-
PHAsset
- 照片库中一个单独的资源(狭隘可以理解为一张图或者一段视频), 以元数据的方式提供, 包含所有该资源的信息(例如, 创建日期, 大小, 类型, 地点, 是否被标记为喜欢等等)
- 用来获取照片库中的PHAsset对象
-
PHLivePhoto(实时照片, 每张照片包含了前后几秒的短视频, 重压可以播放视频, 6s以上机型支持)
- 和
PHAsset
一样也是一个资源包, 不同的是他不仅包含了一张图片,而且还有一段mov格式的视频(拍摄该照片时前后几秒的视频)
- 和
-
PHCollection 有两个子类
PHCollectionList
和PHAssetCollection
-
PHAssetCollection
- 由
PHAsset
组成的集合. 可以理解成一个相册
- 由
-
PHCollectionList
- 表示一组
PHAssetCollection
, 自己本身就是集合类型(可以理解为二维数组), 照片中的年度-精选-时刻
,就是个PHCollectionList
集合. 组PHAssetCollection
, 自己本身就是集合类型(可以理解为二维数组), 照片中的年度-精选-时刻
中的 “年度”,”精选”,”时刻”就是PHAssetCollection类型(一维数组)
- 表示一组
-
PHImageManager
- 请求图片, 视频以及LivePhoto
PHImageRequestOptions
,PHLivePhotoRequestOptions
,PHVideoRequestOptions
分别负责请求图片, LivePhoto和视频的请求参数的配置(例如图片大小)PHCachingImageManager
:负责缓存, 当有大量图片要加载时, 它将图片预加载到内存中
-
PHFetchResult 请求结果集合
-
PHChange: 负责变化一定要注意不论是collection还是asset对象在变化之前都要检验他们能否改变, 通过
canPerformEditOperation
方法检验即可- 当你使用PHPhotoLibrary添加监听之后, 你可以传入一个PHObject或者PHFetchResult对象给PHChange来监听他们的变化
- PHObjectChangeDetails,PHFetchResultChangeDetails分别监听PHObject和PHFetchResult变化
-
PHAssetChangeRequest
- 负责创建, 删除, 修改资源(PHAsset)
- 只能在[PHPhotoLibrary performChanges:] 或者[PHPhotoLibrary performChangesAndWait:]的block中使用
- PHContentEditingInput:对照片进行编辑时作为输入, PHContentEditingInputRequestOptions:对照片编辑时输入照片的参数设置, PHContentEditingOutput: 照片编辑完成之后的输出, PHAdjustmentData: 保存照片编辑过程中的数据, 方便撤回和修改照片的编辑数据.
-
PHAssetCreationRequest: 创建PHAsset对象,并将其保存在照片库中
-
PHAssetCollectionChangeRequest
- 负责资源集合创建, 删除, 修改资源(PHAssetCollection),例如在某个集合中增删改查移等操作
-
PHAssetResource
- 负责将PHAsset资源转化成资源文件(PHAssetResource)
-
它是一种中间产物, 能通过PHAssetResourceManager将其转换成Data, 用于上传服务器
//将PHAsset转化成PHAssetResource对象
- (NSArray<PHAssetResource *> *)assetResourcesForAsset:(PHAsset *)asset;
//将PHLivePhoto转化成PHAssetResource对象
- (NSArray<PHAssetResource *> *)assetResourcesForLivePhoto:(PHLivePhoto *)livePhoto PHOTOS_AVAILABLE_IOS_TVOS(9_1, 10_0);
-
PHAssetResourceManager
-
负责将PHAssetResource资源转化成真正的图片或者视频文件, 用于上传服务器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//将较小PHAssetResource对象(图片或者短视频)转化成NSData类型, 用来上传服务器, 或其他操作 //此方法一般用于转化较小的PHAssetResource对象, 如果太大内存会暴涨, 大文件一般用下面哪个方法 -(PHAssetResourceDataRequestID)requestDataForAssetResource:(PHAssetResource *)resource options:(nullable PHAssetResourceRequestOptions *)options dataReceivedHandler:(void (^)(NSData *data))handler completionHandler:(void(^)(NSError *__nullable error))completionHandler; --------------- //将较大PHAssetResource对象(视频)转化成NSData类型, 并保存到本地, 用来从本地将资源上传服务器, 或其他操作 -(void)writeDataForAssetResource:(PHAssetResource *)resource toFile:(NSURL *)fileURL options:(nullable PHAssetResourceRequestOptions *)options completionHandler:(void(^)(NSError *__nullable error))completionHandler; ------------- //取消转化 - (void)cancelDataRequest:(PHAssetResourceDataRequestID)requestID;
-
使用案例一:
下面以一个常见的使用场景进行 PHAsset 操作过程的描述: 从相册选择图片或视频 — 将图片或视频上传 CDN — 下载图片或视频 — 将图片或视频保存到相册
从相册选择图片 Asset 或视频 Asset
UIImagePickerController 是从相册选取图片 Asset 和视频 Asset 的选择器,利用其进行图片和视频选择结束之后会通过其代理(实现了 UIImagePickerControllerDelegate 协议)执行下面的方法, 将选择结果返回给用户。
1 |
|
Fetching Assets: 从 assets-library URL 获取我们需要的图片和视频 Asset
1 |
|
这些基本信息包含:媒体属性 (mediaType),资源类型 (sourceType),图片像素长宽 (pixelWidth),拍摄地点(location),视频播放时长 (duration) 等。我们下面的例子用到 mediaType 和 mediaSubtypes 两个属性来区分图片,视频和 LivePhoto 三种不同的 Asset。
将图片 Asset 或视频 Asset 转换为真正的文件
经过上面 Fetching Assets 步骤我们已经成功的从 assets-library url 提取出 PHAsset 对象。现在需要把 PHAsset 转换为真正的视频和图片文件。我们要获取的真正文件无非两种:图片文件和视频文件。上面示例涉及的三种 PHAsset,其中视频 Asset 和图片 Asset 可以分别提取视频和图片文件。LivePhoto Asset 既可以提取图片也可以提取视频。
从 PHAsset 获取图片:
1 |
|
既然 mediaType 属性一样,怎么才能具体区分一个 PHAsset 是图片 Asset 还是 LivePhoto 呢,答案是通过 PHAsset 的 mediaSubtypes 属性。
PHAsset 的媒体属性 (mediaType)和二级媒体属性(mediaSubtypes):
1 |
|
可以看到 PHAsset mediaType 可以区分图片,视频和音频。PhotoLive 属于 Photo 类型下面的一个 subtypes。
从 PHAsset 获取视频:
1 |
|
注:上面方法兼顾了从 LivePhoto 里面提取视频文件。
图片或视频文件上传 CDN
上面两段代码具体介绍了 PHAsset 到真正图片文件和视频文件的提取过程。既:可以简单里复用这两个方法来提取真正的 fileData。然后将 fileData 上传到 CDN 或者服务器。
1 |
|
值得注意的是:上述两个接口,最后回调结果是 fileData。对于图片 PHAsset,因为图片文件不会很大,所以直接拿到图片 data 是可以的。但是对于视频 PHAsset,视频文件较大会占用大量内存空间。 我们可以通过修改上面的接口,用视频的 filePath 来替代 fileData,以解决处理大文件视频情况下的内存占用问题。
修改接口,获取 videoFilePath,注意:使用完成,最好手动删除这个临时文件
1 |
|
利用返回的 filePath 可以通过流式的读取文件方式,来组织和发送上传请求的 body 体,达到较好的内存占用。同时又拍云 CDN 提供文件分块上传接口,更适合这种大文件的上传操作。
下载图片和视频保存到手机相册
将图片文件和视频文件保存到手机相册需要以下两个方法:
1 |
|
那么如何保存 LivePhoto,对于支持 LivePhoto 的手机用户可能需要将 LivePhoto 保存到手机相册。但是事实上 LivePhoto 不能作为一个整体文件存在于内存硬盘或者服务器。但是可以将一个视频文件和图片文件一起作为 LivePhoto Asset 保存到相册:
保存 LivePhoto 代码示例:
1 |
|
ALAsset/PHAsset 是属于 iPhone 相册相关操作范围内的概念,ALAsset/PHAsset 并不是文件,不能直接上传 CDN。上传 CDN 需要的真正图片视频文件可以用上文提供的方法从 PHAsset 提取出来。 LivePhoto 属于一种特殊的 PHAsset,可以从 LivePhoto 里面分别提取图片和视频文件之后,再上传 CDN。