版本: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返回这张图像。为了更快的返回,管理器会返回一张目标大小或接近目标大小的图像给你,因为可能之前已经缓存过该图像或生成接近的图像更有效率。
一般来说,回调是异步的并且可以回调多次,通过设置PHImageRequestOptions
的synchronous
为YES来同步回调,同步时只会回调一次,且不能通过cancelImageReques
t取消。
默认情况下,第一次调用回调一般会返回一个合适的低质量图像作为临时展示,然后管理器会去生成一个高质量的图像。当成功生成了高质量的图像后,管理器再次调用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;
管理器会将原图的图像数据回调给你,若
PHImageRequestOptions
的version
为PHImageRequestOptionsVersionCurrent
,管理器会将编辑后的图像数据回调给你。
默认情况下也是异步回调的,也可以设置PHImageRequestOptions
的synchronous
为YES来同步回调。
该方法中PHImageRequestOptions
的deliveryMode
是不生效的。
该方法可运行在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
管理器会将原图的图像数据回调给你,若
PHImageRequestOptions
的version
为PHImageRequestOptionsVersionCurrent
,管理器会将编辑后的图像数据回调给你。
默认情况下也是异步回调的,也可以设置PHImageRequestOptions
的synchronous
为YES来同步回调。
该方法中PHImageRequestOptions
的deliveryMode
是不生效的。
该方法可运行在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