记录Photos框架的使用
前言
这几天项目里用到了图片选择器,就想把之前项目里用ALAssetsLibrary框架封装的图片选择器拿过来用,但是ALAssetsLibrary框架在9.0之后就被弃用了。所以,就要试试Photos框架了。
在网上找了几篇blog研究了一下,就搞了起来。期间也踩了几个坑,所以开篇记录一下。
第一波 获取用户相册
先介绍一些概念,大家可以参考一下这篇blog
- PHAsset:代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源
- PHFetchOptions:获取资源时的参数,可以传 nil,即使用系统默认值
- PHFetchResult:表示一系列的资源集合,也可以是相册的集合
- PHAssetCollection:表示一个相册或者一个时刻,或者是一个「智能相册(系统提供的特定的一系列相册,例如:最近删除,视频列表,收藏等等,如下图所示)
- PHImageManager:用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等规格
- PHImageRequestOptions:如上面所说,控制加载图片时的一系列参数
先上一段获取相册的代码:
1 | //所有智能相册 |
上述方法中的第一第二个参数的类型介绍:
PHAssetCollectionType有三个值:
- album:自定义相册,例如:QQ
- smartAlbum:相机胶卷、我的照片流、屏幕截图、全景照片等
- moment:时刻
PHAssetCollectionSubtype一些值:
- albumRegular:用户在Photos中创建的相册,也就是我所谓的逻辑相册
- albumSyncedEvent:使用iTunes从Photos照片库或者iPhoto照片库同步过来的事件。然而,在iTunes 12以及iOS 9.0 beta4上,选用该类型没法获取同步的事件相册,而必须使用AlbumSyncedAlbum。
- albumSyncedFaces:使用iTunes从Photos照片库或者iPhoto照片库同步的人物相册。
- albumSyncedAlbum:做了AlbumSyncedEvent应该做的事
- albumImported:从相机或是外部存储导入的相册,完全没有这方面的使用经验,没法验证。
从上面的方法中我们可以获取到用户相关的相册,collection.localizedTitle
获取相册名字,对应的中英文对照如下:
1 | ["Slo-mo" : "慢动作", |
第二波 获取相册中的资源
先来一波代码:
1 | let options = PHFetchOptions() |
代码中,通过谓词NSPredicate筛选出所有的照片资源。
PHAssetMediaType有四个值:
- unknown:未知
- image:图片
- video:视频
- audio:音频
PHAsset代表照片库中的一个资源,跟ALAsset类似,通过PHAsset我们可以获取和保存资源。
打印asset显示包含如下信息:
第三波 获取相册里的图片
废话不多说,直接上代码
1 | DispatchQueue.global().async { |
图片的获取是通过PHImageManager来获得,在这里遇到了一个坑,在网上普遍看到的写法如下:
1 | DispatchQueue.global().async { |
代码中不包含requestOptions.isNetworkAccessAllowed = true
此句代码,在模拟器上获取到了图片,但是在真机上调试的时候,打印出来的image = nil,很是纳闷,然后各种搜索查代码,然后把targetSize,给替换成了一个固定的值,结果打印出来的图片尺寸全部都是一样,并不是原图。最后又是各种尝试,查找资料,发现一篇文章里的代码包含这一句requestOptions.isNetworkAccessAllowed = true
代码,然后再去尝试,发现获取原图成功了。应该是PHImageManager需要从Apple方获取原图。
如果想获取自定义的图片尺寸,就按照第一种写法,可以快速的获取到图片。如果想获取原图,就需要按照第二种写法,获取,把注释掉的代码释放出来,这样有一个问题就是,相册图片比较多,图片比较大的时候,加载会比较慢。
第一种写法的requestOptions.resizeMode有三个可选项
- none // no resize 不重设size
- fast // use targetSize as a hint for optimal decoding when the source image is a compressed format (i.e. subsampling), the delivered image may be larger than targetSize (当源图像是压缩格式(即次采样)时,使用Target Size作为最佳解码提示时,交付的图像可能大于Target Size)
- exact // same as above but also guarantees the delivered image is exactly targetSize (must be set when a normalizedCropRect is specified) (与上面相同,但也保证交付的图像是准确的目标大小(必须在指定了规范化的CropRect时设置))
第二种写法的requestOptions.deliveryMode
- opportunistic // client may get several image results when the call is asynchronous or will get one result when the call is synchronous (当调用是异步的时,客户端可能会得到多个映像结果,或者在调用是同步的时候会得到一个结果。)
- highQualityFormat // client will get one result only and it will be as asked or better than asked (sync requests are automatically processed this way regardless of the specified mode)(客户端将只获得一个结果,并且它将被问到或者比被请求的结果更好(同步请求将以这种方式自动处理,而不管指定的模式如何)。)
- fastFormat // client will get one result only and it may be degraded (客户端只会得到一个结果,并且可能会降级。)
具体的详解,可以看开篇提到的这篇blog,有系列的介绍。本次遇到的坑就是这些,记录一下,以防下次再踩。结尾,谢谢网上各位的分享,让知识传播起来。本文源码请戳这里