PhotoKit制作相册或选择器(一):初识Photos

前言

不知读者们在平日里使用聊天工具时,有没有发表情的习惯。是不是常常在与朋友们聊天时,一言不合就掀起一场斗图大会呢。小编作为一个喜欢搞事情的小码农,上班唯一能放松的事情就是和同事在群里吹牛逼斗斗图了(不搞点事情代码怎么吐的动呢)。
找不到图源,微信表情又有上限等,种种问题让我施展不出真正的斗图实力(中毒太深)。非得搞点事情的我计划开发一款制作管理GIF表情的相册,名字叫斗逗图(目前五菱宏光版正在审核中......)
这波广告小编打得自己都脸红了。。。那来切入正题吧,在开发过程中,我需要通过图片选择器选择多张图片,可是强大的UIImagePickerController却没有多选功能,这让我很忧桑,看了看Github,已经有比较好的轮子,但样式固定死了,太花哨了,毕竟咱是五菱宏光,漂移之王,花哨的轮子漂不起来,还是自己用Photos造一个吧。

关于Photos

资源

PHObject:资源基类,PHAssetPHCollecton等都继承它,它包含了一个属性localIdentifier,它是唯一的,所以我们可以通过此属性来判断资源对象是否是同一个
PHAsset:代表一个在相册中的图片或视频,它本身并不储存图片或视频资源,它存放的是metaData,需要通过PHImageManager来请求才能获取图片或视频资源。
PHCollection:照片库中单独轻量不可变的集合对象
PHAssetCollectionPHCollection的子类,可以通过它获取系统自带的相册信息
PHCollectionList:既是PHCollection的子类,也是PHCollection的集合
PHFetchResult:很像NSFetchRequest吧,它也有predicatesortDescriptors;使用起来,它类似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决定了图片如何改变
(详细可看PHImageRequestOptionsDeliveryModePHImageRequestOptionsResizeMode)

  •  **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
    用于对原始尺寸的图像进行裁剪,基于比例坐标。只在 resizeModeExact 时有效。
resultHandler

此代码块是异步执行的,如果deliveryMode等于PHImageRequestOptionsDeliveryModeOpportunistic时,先会同步返回一个临时的低质量资源,之后当请求到所需的图片资源时,会异步返回;options 参数的作用就是来定制这些行为

请求LivePhoto

请求LivePhoto资源。如果 PHLivePhotoRequestOptions
deliveryMode
PHImageRequestOptionsDeliveryModeOpportunistic或者optionsnil时,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的作用就体现出来了
顾名思义,它就类似一个观察者,监测变化,反应变化。
使用步骤:

  1. 添加此协议<PHPhotoLibraryChangeObserver>
- (void)viewWillAppear:(BOOL)animated {
    //注册观察相册变化的观察者
    [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
}
- (void)dealloc {
    //销毁观察相册变化的观察者
    [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
}

2.实现协议

- (void)photoLibraryDidChange:(PHChange *)changeInstance;

PHChangechangeDetailsForFetchResult:方法检测照片集合内是否产生变化,入参为被检测的照片集合

- (nullable PHFetchResultChangeDetails *)changeDetailsForFetchResult:(PHFetchResult *)object;

结束语

以上是关于Photos框架的简单介绍,一些基本的用法,足够开发一款简单的相册或者选择器啦!
这回买好零件,下一篇就开始造我们五菱宏光专属轮子了。
敬请期待~

小编对文档的理解可能会有些出入,有错误希望读者能积极指出,我会及时更正。
如果喜欢,请持续关注,顺便点个喜欢噢👇👇👇

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容