前言
不知读者们在平日里使用聊天工具时,有没有发表情的习惯。是不是常常在与朋友们聊天时,一言不合就掀起一场斗图大会呢。小编作为一个喜欢搞事情的小码农,上班唯一能放松的事情就是和同事在群里吹牛逼斗斗图了(不搞点事情代码怎么吐的动呢)。
找不到图源,微信表情又有上限等,种种问题让我施展不出真正的斗图实力(中毒太深)。非得搞点事情的我计划开发一款制作管理GIF表情的相册,名字叫斗逗图(目前五菱宏光版正在审核中......)
这波广告小编打得自己都脸红了。。。那来切入正题吧,在开发过程中,我需要通过图片选择器选择多张图片,可是强大的UIImagePickerController
却没有多选功能,这让我很忧桑,看了看Github,已经有比较好的轮子,但样式固定死了,太花哨了,毕竟咱是五菱宏光,漂移之王,花哨的轮子漂不起来,还是自己用Photos造一个吧。
关于Photos
资源
PHObject:资源基类,PHAsset
、PHCollecton
等都继承它,它包含了一个属性localIdentifier
,它是唯一的,所以我们可以通过此属性来判断资源对象是否是同一个
PHAsset:代表一个在相册中的图片或视频,它本身并不储存图片或视频资源,它存放的是metaData
,需要通过PHImageManager
来请求才能获取图片或视频资源。
PHCollection:照片库中单独轻量不可变的集合对象
PHAssetCollection:PHCollection
的子类,可以通过它获取系统自带的相册信息
PHCollectionList:既是PHCollection
的子类,也是PHCollection
的集合
PHFetchResult:很像NSFetchRequest
吧,它也有predicate
和sortDescriptors
;使用起来,它类似NSArray
,可以通过遍历获取储存的各个元素;还能通过观察者模式来检测相册内容是否变化。
获取资源
PHAssetCollection类方法获取相册的资源
#pragma mark - Fetching asset collections
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithType:(PHAssetCollectionType)type subtype:(PHAssetCollectionSubtype)subtype options:(nullable PHFetchOptions *)options;
// Smart Albums are not supported, only Albums and Moments
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsContainingAsset:(PHAsset *)asset withType:(PHAssetCollectionType)type options:(nullable PHFetchOptions *)options;
// assetGroupURLs are URLs retrieved from ALAssetGroup's ALAssetsGroupPropertyURL
+ (PHFetchResult<PHAssetCollection *> *)fetchAssetCollectionsWithALAssetGroupURLs:(NSArray<NSURL *> *)assetGroupURLs options:(nullable PHFetchOptions *)options;
#pragma mark - Fetching moment asset collections
+ (PHFetchResult<PHAssetCollection *> *)fetchMomentsInMomentList:(PHCollectionList *)momentList options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAssetCollection *> *)fetchMomentsWithOptions:(nullable PHFetchOptions *)options;
PHAsset类方法获取分类过后的资源
#pragma mark - Fetching assets
+ (PHFetchResult<PHAsset *> *)fetchAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithLocalIdentifiers:(NSArray<NSString *> *)identifiers options:(nullable PHFetchOptions *)options;
+ (nullable PHFetchResult<PHAsset *> *)fetchKeyAssetsInAssetCollection:(PHAssetCollection *)assetCollection options:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithBurstIdentifier:(NSString *)burstIdentifier options:(nullable PHFetchOptions *)options;
// Fetches PHAssetSourceTypeUserLibrary assets by default (use includeAssetSourceTypes option to override)
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithOptions:(nullable PHFetchOptions *)options;
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithMediaType:(PHAssetMediaType)mediaType options:(nullable PHFetchOptions *)options;
// assetURLs are URLs retrieved from ALAsset's ALAssetPropertyAssetURL
+ (PHFetchResult<PHAsset *> *)fetchAssetsWithALAssetURLs:(NSArray<NSURL *> *)assetURLs options:(nullable PHFetchOptions *)options;
返回的类型都是PHFetchResult
,里面存放的并不是一个个的图片原始资源,而只是一个个包含元数据的PHAsset
。那我们该如何获取图片的原始资源呢?这就该用到PHImageManager
类。
请求资源
PHImageManager
此类提供了请求加载图片或视频数据的方法,既可以获取原始大小的图片,也能获取缩略图,同时也可以取回用作播放的AVFoundation相关对象或者操作视频资源。
当同时加载多个资源很快显示出来时, 可以使用PHCachingImageManager
类预加载图片至缓存,这个会在之后的文章中写到。
以下方法都是实例方法,调用时需要使用defaultManager
请求图片
方法列表:
#pragma mark - Image
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;
// resultHandler for asynchronous requests, always called on main thread
- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset options:(nullable PHImageRequestOptions *)options resultHandler:(void(^)(NSData *__nullable imageData, NSString *__nullable dataUTI, UIImageOrientation orientation, NSDictionary *__nullable info))resultHandler;
//请求方法都返回了PHImageRequestID,可以通过此ID来取消请求
- (void)cancelImageRequest:(PHImageRequestID)requestID;
targetSize
目标尺寸
contentMode
如果资源的比例与所给的目标大小不匹配的话,contentMode
决定了图片如何改变
(详细可看PHImageRequestOptionsDeliveryMode和PHImageRequestOptionsResizeMode)
**PHImageContentModeAspectFit**:使图片根据目标大小完整显示
**PHImageContentModeAspectFill**:使图片根据目标大小裁剪显示
**PHImageContentModeDefault**: 当尺寸设置为```PHImageManagerMaximumSize```时使用```PHImageContentModeDefault```,得到的结果没有经过缩放和裁剪
options
-
version:
当version
等于PHImageRequestOptionsVersionCurrent
请求返回资源是已经调整过后最大的图片数据 -
synchronous:
请求是否同步执行,值为NO
时,会根据deliveryMode
这个属性,等待方法的回调;当为YES
时,deliveryMode
的值会被忽略,resultHandler
这个回调也只会执行一次 - resizeMode:图像变化方式。
Fast:尽快地提供接近要求的尺寸;
Exact:精准提供要求的尺寸。
deliveryMode:图像质量。
Opportunistic:临时图像;
HighQualityFormat:高质量图像;
FastFormat,以最快速度提供好的质量。 这个属性只有在 synchronous 为 true 时有效。
-
normalizedCropRect:
用于对原始尺寸的图像进行裁剪,基于比例坐标。只在resizeMode
为Exact
时有效。
resultHandler
此代码块是异步执行的,如果deliveryMode
等于PHImageRequestOptionsDeliveryModeOpportunistic
时,先会同步返回一个临时的低质量资源,之后当请求到所需的图片资源时,会异步返回;options
参数的作用就是来定制这些行为
请求LivePhoto
请求LivePhoto资源。如果 PHLivePhotoRequestOptions
的deliveryMode
为PHImageRequestOptionsDeliveryModeOpportunistic
或者options
为nil
时,resultHandler
回调不止一次,并且有可能会在同步方法返回前先返回
resultHandler
回调代码块的Info
字典PHImageResultIsDegradedKey
对应的值代表是否低质量的LivePhoto已经提供
#pragma mark - Live Photo
//Live Photo
- (PHImageRequestID)requestLivePhotoForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHLivePhotoRequestOptions *)options resultHandler:(void (^)(PHLivePhoto *__nullable livePhoto, NSDictionary *__nullable info))resultHandler NS_AVAILABLE_IOS(9_1);
请求视频
#pragma mark - Video
//可播放视频音频资源
- (PHImageRequestID)requestPlayerItemForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVPlayerItem *__nullable playerItem, NSDictionary *__nullable info))resultHandler;
// 导出会话
- (PHImageRequestID)requestExportSessionForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options exportPreset:(NSString *)exportPreset resultHandler:(void (^)(AVAssetExportSession *__nullable exportSession, NSDictionary *__nullable info))resultHandler;
// 其他
- (PHImageRequestID)requestAVAssetForVideo:(PHAsset *)asset options:(nullable PHVideoRequestOptions *)options resultHandler:(void (^)(AVAsset *__nullable asset, AVAudioMix *__nullable audioMix, NSDictionary *__nullable info))resultHandler;
观察相册变更
相册里多了一张照片,如何及时的显示出来呢?
此时PHPhotoLibraryChangeObserver的作用就体现出来了
顾名思义,它就类似一个观察者,监测变化,反应变化。
使用步骤:
- 添加此协议
<PHPhotoLibraryChangeObserver>
- (void)viewWillAppear:(BOOL)animated {
//注册观察相册变化的观察者
[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
}
- (void)dealloc {
//销毁观察相册变化的观察者
[[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
}
2.实现协议
- (void)photoLibraryDidChange:(PHChange *)changeInstance;
PHChange
的changeDetailsForFetchResult:
方法检测照片集合内是否产生变化,入参为被检测的照片集合
- (nullable PHFetchResultChangeDetails *)changeDetailsForFetchResult:(PHFetchResult *)object;
结束语
以上是关于Photos框架的简单介绍,一些基本的用法,足够开发一款简单的相册或者选择器啦!
这回买好零件,下一篇就开始造我们五菱宏光专属轮子了。
敬请期待~
小编对文档的理解可能会有些出入,有错误希望读者能积极指出,我会及时更正。
如果喜欢,请持续关注,顺便点个喜欢噢👇👇👇