PHImageManager的使用

版本:iOS13.7

一、简介

PHImageManager是一个专门请求图像与视频的类。每次请求完成后,会对已请求的图像与视频作缓存。当下次使用相同的图像与视频时,会更快的返回结果。
PHCachingImageManager是PHImageManager的子类,其作用是预先缓存图像与视频,以便请求的时候能更快返回。

二、PHImageManager的API

  • 全局单例方法,返回PHImageManager的实例。
+ (PHImageManager *)defaultManager;
Image
  • 请求指定asset的图像。
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize
                    contentMode:(PHImageContentMode)contentMode 
                    options:(nullable PHImageRequestOptions *)options
                     resultHandler:(void (^)(UIImage *_Nullable result, 
                                             NSDictionary *_Nullable info))resultHandler

管理器会加载或生成一张图像并通过resultHandler返回这张图像。为了更快的返回,管理器会返回一张目标大小或接近目标大小的图像给你,因为可能之前已经缓存过该图像或生成接近的图像更有效率。
一般来说,回调是异步的并且可以回调多次,通过设置PHImageRequestOptionssynchronous为YES来同步回调,同步时只会回调一次,且不能通过cancelImageRequest取消。
默认情况下,第一次调用回调一般会返回一个合适的低质量图像作为临时展示,然后管理器会去生成一个高质量的图像。当成功生成了高质量的图像后,管理器再次调用resultHandler来返回这张图像。若管理器已经缓存了请求图像的高质量图像,管理器只会调用一次resultHandler并直接返回高质量图像。可通过resultHandler中的info中的PHImageResultIsDegradedKey判断是否为高质量图像。

若PHAsset是一个视频时,则会回调该视频的缩略图或关键帧。

asset 要加载其图像数据的PHAsset
targetSize 要返回的图像的目标尺寸 PHImageManagerMaximumSize是表示最大尺寸
contentMode 图像自适应模式。
当图像的宽高比与目标尺寸不一致时,通过contentMode决定该如何适应。

typedef NS_ENUM(NSInteger, PHImageContentMode) {
    //压缩模式 图像的长边与目标尺寸一致,短边则比例缩小,小于目标尺寸。
    PHImageContentModeAspectFit = 0,
    //伸展模式 图像的短边与目标尺寸一致,长边则比例放大,超出日标尺寸的部分会被切掉
    PHImageContentModeAspectFill = 1,
    //默认
    PHImageContentModeDefault = PHImageContentModeAspectFit
};

options 图像请求选项,详见 PHImageRequestOptions说明
resultHandler 在当前线程上同步或在主线程上异步调用一次或多次的block

void (^)(UIImage *_Nullable result, NSDictionary *_Nullable info)
result 请求成功的图像
info 图像的信息

字典的key value
PHImageResultIsInCloudKey NSNumber 
结果在iCloud中,需要发出新请求(PHImageRequestOptions.networkAccessAllowed = YES)才能获得结果

PHImageResultIsDegradedKey NSNumber
返回的图像是降级的(仅针对异步请求)
这意味着将发送其他图像,除非与此同时取消请求
如果本地数据不可用且networkAccessAllowed不为YES,则请求可能会失败

PHImageResultRequestIDKey NSNumber
请求的id

PHImageCancelledKey NSNumber
结果不可用,因为请求已被取消

PHImageErrorKey NSError
从iCloud获取失败的错误

return PHImageRequestID 请求的数字标识符 可通过调用cancelImageRequest取消请求,只能取消异步的请求。

  • 请求指定asset的图像数据。
- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset 
         options:(nullable PHImageRequestOptions *)options 
         resultHandler:(void (^)(NSData *_Nullable imageData, NSString *_Nullable dataUTI,
              UIImageOrientation orientation, NSDictionary *_Nullable info))resultHandler;

管理器会将原图的图像数据回调给你,若PHImageRequestOptionsversionPHImageRequestOptionsVersionCurrent,管理器会将编辑后的图像数据回调给你。
默认情况下也是异步回调的,也可以设置PHImageRequestOptionssynchronous为YES来同步回调。
该方法中PHImageRequestOptionsdeliveryMode是不生效的。

该方法可运行在ios(8, 13),iOS13以后使用requestImageDataAndOrientationForAsset:options:resultHandler:

参数参考requestImageForAsset
resultHandler 图像加载完成的回调

void (^)(NSData *_Nullable imageData, NSString *_Nullable dataUTI,
              UIImageOrientation orientation, NSDictionary *_Nullable info)
imageData 图像数据
dataUTI 图像的名字
orientation 图像展示的方向
info 图像的信息

UIImageOrientation 图像方向

typedef NS_ENUM(NSInteger, UIImageOrientation) {
    UIImageOrientationUp,            //正常
    UIImageOrientationDown,          //旋转180度
    UIImageOrientationLeft,          // 逆时针旋转90度
    UIImageOrientationRight,         // 正时针旋转90度
    UIImageOrientationUpMirrored,    // 左右翻转
    UIImageOrientationDownMirrored,  // 旋转180度后再左右翻转
    UIImageOrientationLeftMirrored,  // 逆时针旋转90度再左右翻转
    UIImageOrientationRightMirrored, // 正时针旋转90度再左右翻转
};
  • 请求指定asset的图像数据和EXIF方向
- (PHImageRequestID)requestImageDataAndOrientationForAsset:(PHAsset *)asset
       options:(nullable PHImageRequestOptions *)options 
       resultHandler:(void (^)(NSData *_Nullable imageData, NSString *_Nullable dataUTI, 
       CGImagePropertyOrientation orientation, NSDictionary *_Nullable info))resultHandler

管理器会将原图的图像数据回调给你,若PHImageRequestOptionsversionPHImageRequestOptionsVersionCurrent,管理器会将编辑后的图像数据回调给你。
默认情况下也是异步回调的,也可以设置PHImageRequestOptionssynchronous为YES来同步回调。
该方法中PHImageRequestOptionsdeliveryMode是不生效的。

该方法可运行在ios(13),iOS13以前使用requestImageDataForAsset:

参数参考requestImageForAsset
resultHandler 图像加载完成的回调

void (^)(NSData *_Nullable imageData, NSString *_Nullable dataUTI, 
       CGImagePropertyOrientation orientation, NSDictionary *_Nullable info)
imageData 图像数据
dataUTI 图像的名字
orientation 图像的EXIF方向
info 图像的信息

CGImagePropertyOrientation EXIF方向
对于iOS或tvOS,请将其转换为UIImageOrientation。

typedef CF_CLOSED_ENUM(uint32_t, CGImagePropertyOrientation) {
    kCGImagePropertyOrientationUp = 1,    
    kCGImagePropertyOrientationUpMirrored,    
    kCGImagePropertyOrientationDown,         
    kCGImagePropertyOrientationDownMirrored,  
    kCGImagePropertyOrientationLeftMirrored,  
    kCGImagePropertyOrientationRight,         
    kCGImagePropertyOrientationRightMirrored,
    kCGImagePropertyOrientationLeft           
};
可通过下面方法转换
- (CGImagePropertyOrientation)imagePropertyOrientationWithOrientation:(UIImageOrientation)orientation {
 switch (orientation) {
     case UIImageOrientationUp:
         return kCGImagePropertyOrientationUp;
     case UIImageOrientationUpMirrored:
         return kCGImagePropertyOrientationUpMirrored;
     case UIImageOrientationDown:
         return kCGImagePropertyOrientationDown;
     case UIImageOrientationDownMirrored:
         return kCGImagePropertyOrientationDownMirrored;
     case UIImageOrientationLeftMirrored:
         return kCGImagePropertyOrientationLeftMirrored;
     case UIImageOrientationRight:
         return kCGImagePropertyOrientationRight;
     case UIImageOrientationRightMirrored:
         return kCGImagePropertyOrientationRightMirrored;
    case UIImageOrientationLeft:
         return kCGImagePropertyOrientationLeft;
 }
}
  • 取消图像的请求
- (void)cancelImageRequest:(PHImageRequestID)requestID;

只能取消异步回调的请求。

PHImageRequestOptions说明

//图像的版本
@property (nonatomic, assign) PHImageRequestOptionsVersion version;

typedef NS_ENUM(NSInteger, PHImageRequestOptionsVersion) {
    //若图像进行了编辑,会返回编辑后的版本
    PHImageRequestOptionsVersionCurrent = 0, 
    //返回没做任何调整的原始版本
    PHImageRequestOptionsVersionUnadjusted, 
    //返回原始版本,如果是组合格式,则将返回最高保真度格式(例如RAW表示RAW + JPG源图像)
    PHImageRequestOptionsVersionOriginal 
};

//交付模式
@property (nonatomic, assign) PHImageRequestOptionsDeliveryMode deliveryMode;

typedef NS_ENUM(NSInteger, PHImageRequestOptionsDeliveryMode) {
    //默认 异步调用时可能会得到多个图像结果,或者在同步调用时会得到一个结果
    PHImageRequestOptionsDeliveryModeOpportunistic = 0, 
    //只会得到一个结果,它将是所要求的或比之更好的结果
    PHImageRequestOptionsDeliveryModeHighQualityFormat = 1, 
    //只会得到一个结果,它可能会是降级的结果 
    PHImageRequestOptionsDeliveryModeFastFormat = 2 // 
};

//调整大小模式
//当targetSize为PHImageManagerMaximumSize时不生效
@property (nonatomic, assign) PHImageRequestOptionsResizeMode resizeMode;

typedef NS_ENUM(NSInteger, PHImageRequestOptionsResizeMode) {
    //不调整大小
    PHImageRequestOptionsResizeModeNone = 0, 
    //默认 
    //当源图像为压缩格式(即二次采样)时,会使用targetSize作为最佳解码的大小,但交付的图像可能大于targetSize
    PHImageRequestOptionsResizeModeFast, 
    //与上述相同,但交付的图像等于targetSize(必须在设置normalizedCropRect时才生效)
    PHImageRequestOptionsResizeModeExact, 
};

//在原始图像的单位坐标中指定的裁剪矩形。
//当resizeMode = PHImageRequestOptionsResizeModeExact才生效。
//默认为CGRectZero
@property (nonatomic, assign) CGRect normalizedCropRect;
//允许从iCloud下载图像,默认为NO。
//可以通过progressHandler监视或取消下载
@property (nonatomic, assign, getter=isNetworkAccessAllowed) BOOL networkAccessAllowed;
//是否同步请求图像,默认为NO。
//仅返回一个结果,会阻塞线程直到请求成功(或失败)。
@property (nonatomic, assign, getter=isSynchronous) BOOL synchronous;
//当从iCloud下载图像时,将会回调该handler,默认为nil
@property (nonatomic, copy, nullable) PHAssetImageProgressHandler progressHandler;

typedef void (^PHAssetImageProgressHandler)
  (double progress, NSError *__nullable error, BOOL *stop, NSDictionary *__nullable info);

progress 当前的进度
error 下载失败的错误
stop 停止标志 设置YES可取消下载
info 下载的数据

Live Photo
  • 请求指定asset的实况照片。
- (PHImageRequestID)requestLivePhotoForAsset:(PHAsset *)asset 
              targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode 
              options:(nullable PHLivePhotoRequestOptions *)options 
             resultHandler:(void (^)(PHLivePhoto *__nullable livePhoto, 
                                    NSDictionary *__nullable info))resultHandler

livePhoto(实况照片)是一种包含了拍摄时之后时刻的画面和声音的照片。可以使用PHLivePhotoView来展示livePhoto的动态效果。

requestImageForAsset方法有相同之处,为了更快的返回,管理器也会返回一张目标大小或接近目标大小的livePhoto。同样的,管理器也会先返回低质量的livePhoto,加载完成后,再返回高质量的livePhoto。若缓存中已经有高质量的livePhoto了,就会直接返回。

当PHAsset为livePhoto时,调用requestImageForAsset则会返回静止图像。

参数参考requestImageForAsset
options 实况照片选项
PHLivePhotoRequestOptions参考 PHImageRequestOptions说明
resultHandler livePhoto加载完成的回调

void (^)(PHLivePhoto *__nullable livePhoto, NSDictionary *__nullable info)
livePhoto 实况照片对象
info 实况照片的信息
Video
  • 请求指定asset的视频播放项
- (PHImageRequestID)requestPlayerItemForVideo:(PHAsset *)asset 
                    options:(nullable PHVideoRequestOptions *)options 
                    resultHandler:(void (^)(AVPlayerItem *__nullable playerItem, 
                                            NSDictionary *__nullable info))resultHandler

管理器会异步加载并返回仅用于播放的AVPlayerItem,可通过[AVPlayer playerWithPlayerItem:playerItem]来创建播放器。

asset 要加载其视频的PHAsset
options 视频请求选项 详见PHVideoRequestOptions说明
resultHandler 视频加载完成的回调

void (^)(AVPlayerItem *__nullable playerItem, NSDictionary *__nullable info)
playerItem 视频对象
info 视频的信息
  • 请求指定asset的视频导出会话
- (PHImageRequestID)requestExportSessionForVideo:(PHAsset *)asset 
   options:(nullable PHVideoRequestOptions *)options exportPreset:(NSString *)exportPreset 
   resultHandler:(void (^)(AVAssetExportSession *__nullable exportSession, 
                           NSDictionary *__nullable info))resultHandler

管理器会异步加载并返回导出会话AVAssetExportSession,导出会话的功能是将AVAsset压缩并导出到沙盒。

参数参考requestPlayerItemForVideo
exportPreset 导出会话的预设名
resultHandler 视频加载完成并准备导出会话时的回调

void (^)(AVAssetExportSession *__nullable exportSession,  NSDictionary *__nullable info)
exportSession 导出会话
info 视频的信息
  • 请求指定asset的视频
- (PHImageRequestID)requestAVAssetForVideo:(PHAsset *)asset 
             options:(nullable PHVideoRequestOptions *)options 
             resultHandler:(void (^)(AVAsset *__nullable asset, 
             AVAudioMix *__nullable audioMix, NSDictionary *__nullable info))resultHandler

管理器会异步加载并返回视频对象AVAsset,AVAsset保存了视频的各种属性。
可使用[AVPlayerItem playerItemWithAsset:asset]创建播放项。

参数参考requestPlayerItemForVideo
resultHandler 视频加载完成的回调

void (^)(AVAsset *__nullable asset, 
         AVAudioMix *__nullable audioMix, NSDictionary *__nullable info)
asset 视频对象
audioMix 视频的混合音频 若为nil表示使用的是默认音频
info 视频的信息
PHVideoRequestOptions说明

//允许从iCloud下载视频,默认为NO。
//可以通过progressHandler监视或取消下载
@property (nonatomic, assign, getter=isNetworkAccessAllowed) BOOL networkAccessAllowed;
//版本
@property (nonatomic, assign) PHVideoRequestOptionsVersion version;

typedef NS_ENUM(NSInteger, PHVideoRequestOptionsVersion) {
    //若视频进行了编辑,会返回编辑后的版本
    PHVideoRequestOptionsVersionCurrent = 0, 
    //返回原始的版本
    PHVideoRequestOptionsVersionOriginal
};

//交付模式
//只有version = PHVideoRequestOptionsVersionCurrent才生效
@property (nonatomic, assign) PHVideoRequestOptionsDeliveryMode deliveryMode;

typedef NS_ENUM(NSInteger, PHVideoRequestOptionsDeliveryMode) { 
    //自动模式 
    //AVPlayerItem和AVAsset,会使用PHVideoRequestOptionsDeliveryModeMediumQualityFormat
    //AVAssetExportSession,会使用PHVideoRequestOptionsDeliveryModeHighQualityFormat
    PHVideoRequestOptionsDeliveryModeAutomatic = 0, 
    //高质量
    PHVideoRequestOptionsDeliveryModeHighQualityFormat = 1, 
    //中质量(典型值720p)
    //从iCloud下载且返回AVPlayerItem或AVAsset时,默认使用中质量
    //若本地可用,则默认使用高质量
    PHVideoRequestOptionsDeliveryModeMediumQualityFormat = 2, 
    //最快可用质量(典型值360p MP4)
    //从iCloud下载且返回AVPlayerItem或AVAsset时,默认使用最快可用质量
    //若本地可用,则默认使用高质量
    PHVideoRequestOptionsDeliveryModeFastFormat = 3
};

//当从iCloud下载图像时,将会回调该handler,默认为nil
@property (nonatomic, copy, nullable) PHAssetVideoProgressHandler progressHandler;

typedef void (^PHAssetVideoProgressHandler)(double progress, NSError *__nullable error,
                                            BOOL *stop, NSDictionary *__nullable info);

progress 当前的进度
error 下载失败的错误
stop 停止标志 设置YES可取消下载
info 下载的数据

三、PHCachingImageManager的API

当调用requestImageForAsset:获取图像时,如果请求的图像已经缓存好了,PHCachingImageManager会立刻返回这个图像。否则,管理器会加载这个图像,完成后返回并缓存图像以备下次使用。

@interface PHCachingImageManager : PHImageManager

//允许缓存高质量图像,默认为YES
//若在滚动操作前有时间缓存,最好设为YES,缓存后在滚动时会更快地加载出图像
//若没有时间缓存,应该设为NO,以便在滚动时能更快的缓存好且快速地加载
@property (nonatomic, assign) BOOL allowsCachingHighQualityImages; 

//异步地缓存图像,但只缓存了图像源(在缓存时并没有对它们进行裁剪或精确调整大小,只有在使用时才进行交付)。
//如果使用不同的options或不同的targetSize进行了多个缓存请求,则第一个缓存请求将具有优先级。(直到停止)
//assets 要缓存的PHAsset数组
//targetSize 目标大小
//contentMode 图像自适应模式 详见requestImageForAsset:
//options 图像请求选项 详见 PHImageRequestOptions说明
- (void)startCachingImagesForAssets:(NSArray<PHAsset *> *)assets targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options;
//停止缓存 
//若已经缓存,则会取消该缓存。
//targetSize和options必须和startCachingImagesForAssets方法设置的相同
- (void)stopCachingImagesForAssets:(NSArray<PHAsset *> *)assets targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options;
//停止所有缓存
- (void)stopCachingImagesForAllAssets;

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