之前基于AssetsLibrary的框架封装过相册的单选与多选,不过ALAssetLibrary的方法在iOS 9中不被推荐了,现在用新的框架PhotoKit的来替代。
首先先了解一下photoKit的框架。photoKit的基本构成有:
1、PHAsset: 代表照片库中的一个资源,跟 ALAsset 类似,通过 PHAsset 可以获取和保存资源
2、PHFetchOptions: 获取资源时的参数,可以传 nil,即使用系统默认值
3、PHAssetCollection: PHCollection 的子类,表示一个相册或者一个时刻,或者是一个「智能相册(系统提供的特定的一系列相册,例如:最近删除,视频列表,收藏等等,如下图所示)
4、PHFetchResult: 表示一系列的资源结果集合,也可以是相册的集合,从 PHCollection 的类方法中获得
5、PHImageManager: 用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等规格
PHImageRequestOptions: 如上面所说,控制加载图片时的一系列参数
6、PHCollectionList,表示一组 PHCollection,它本身也是一个 PHCollection,因此 PHCollection 作为一个集合,可以包含其他集合,这使到 PhotoKit 的组成比 ALAssetLibrary 要复杂一些。另外与 ALAssetLibrary 相似,一个 PHAsset 可以同时属于多个不同的 PHAssetCollection,最常见的例子就是刚刚拍摄的照片,至少同时属于“最近添加”、“相机胶卷”以及“照片 - 精选”这三个 PHAssetCollection.
概念图如下:
具体上代码:
封装的几个方法:
/*
* 获取全部相册
*/
-(NSMutableArray *)getPhotoListDatas;
/*
* 获取某一个相册的结果集
*/
-(PHFetchResult *)getFetchResult:(PHAssetCollection *)assetCollection;
/*
* 获取图片实体,并把图片结果存放到数组中,返回值数组
*/
-(NSMutableArray *)getPhotoAssets:(PHFetchResult *)fetchResult;
/*
* 只获取相机胶卷结果集
*/
-(PHFetchResult *)getCameraRollFetchResul;
实现:
-(NSMutableArray *)getPhotoListDatas{
NSMutableArray *dataArray = [NSMutableArray array];
//获取资源时的参数,为nil时则是使用系统默认值
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc]init];
//列出所有的智能相册
PHFetchResult *smartAlbumsFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:fetchOptions];
[dataArray addObject:[smartAlbumsFetchResult objectAtIndex:0]];
//列出所有用户创建的相册
PHFetchResult *smartAlbumsFetchResult1 = [PHAssetCollection fetchTopLevelUserCollectionsWithOptions:fetchOptions];
//遍历
for (PHAssetCollection *sub in smartAlbumsFetchResult1) {
[dataArray addObject:sub];
}
return dataArray;
}
-(PHFetchResult *)getFetchResult:(PHAssetCollection *)assetCollection{
//获取某个相册的结果集
PHFetchResult *fetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
return fetchResult;
}
-(NSMutableArray *)getPhotoAssets:(PHFetchResult *)fetchResult{
NSMutableArray *dataArray = [NSMutableArray array];
for (PHAsset *asset in fetchResult) {
//只添加图片类型资源,去除视频类型资源
//当mediatype == 2时,之歌资源则视为视频资源
NSLog(@"%ld",asset.mediaSubtypes);
if (asset.mediaSubtypes == 0) {
[dataArray addObject:asset];
}
}
return dataArray;
}
-(PHFetchResult *)getCameraRollFetchResul{
//获取系统相册CameraRoll 的结果集
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc]init];
PHFetchResult *smartAlbumsFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:fetchOptions];
PHFetchResult *fetch = [PHAsset fetchAssetsInAssetCollection:[smartAlbumsFetchResult objectAtIndex:0] options:nil];
return fetch;
}
-(void)getImageObject:(id)asset complection:(void (^)(UIImage *, BOOL))complection{
if ([asset isKindOfClass:[PHAsset class]]) {
PHAsset *phAsset = (PHAsset *)asset;
CGFloat photoWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat aspectRatio = phAsset.pixelWidth / (CGFloat)phAsset.pixelHeight;
//屏幕分辨率 scale = 1 代表 分辨率是320 * 480; = 2 代表 分辨率是 640 * 960; = 3 代表 分辨率是 1242 * 2208
CGFloat multiple = [UIScreen mainScreen].scale;
CGFloat pixelWidth = photoWidth * multiple;
CGFloat pixelHeight = pixelWidth / aspectRatio;
/**
* PHImageManager 是通过请求的方式拉取图像,并可以控制请求得到的图像的尺寸、剪裁方式、质量,缓存以及请求本身的管理(发出请求、取消请求)等
*
* @param pixelWidth 获取图片的宽
* @param pixelHeight 获取图片的高
* @param contentMode 图片的剪裁方式
*
* @return
*/
[[PHImageManager defaultManager] requestImageForAsset:phAsset targetSize:CGSizeMake(pixelWidth, pixelHeight) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// 排除取消,错误,低清图三种情况,即已经获取到了高清图
BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
if (downloadFinined) {
//回调
if (complection){
complection(result,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
}
}
}];
}
}
具体说一下一下这个方法:
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset
targetSize:(CGSize)targetSize
contentMode:(PHImageContentMode)contentMode
options:(nullable PHImageRequestOptions *)options
resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;
这个方法中的参数坑点不少,下面逐个参数列举一下其作用及坑点:
1、asset,图像对应的 PHAsset。
2、targetSize,需要获取的图像的尺寸,如果输入的尺寸大于资源原图的尺寸,则只返回原图。需要注意在 PHImageManager 中,所有的尺寸都是用 Pixel 作为单位(Note that all sizes are in pixels),因此这里想要获得正确大小的图像,需要把输入的尺寸转换为 Pixel。如果需要返回原图尺寸,可以传入 PhotoKit 中预先定义好的常量?PHImageManagerMaximumSize,表示返回可选范围内的最大的尺寸,即原图尺寸。
3、 contentMode,图像的剪裁方式,与?UIView 的 contentMode 参数相似,控制照片应该以按比例缩放还是按比例填充的方式放到最终展示的容器内。注意如果 targetSize 传入?PHImageManagerMaximumSize,则 contentMode 无论传入什么值都会被视为?PHImageContentModeDefault。
4、options,一个?PHImageRequestOptions 的实例,可以控制的内容相当丰富,包括图像的质量、版本,也会有参数控制图像的剪裁,下面再展开说明。
5、resultHandler,请求结束后被调用的 block,返回一个包含资源对于图像的 UIImage 和包含图像信息的一个 NSDictionary,在整个请求的周期中,这个 block 可能会被多次调用,关于这点连同 options 参数在下面展开说明。
最后封装了一个demo,实现图片的多选与单选。具体效果如下:
具体的demo下载地址:http://download.youkuaiyun.com/detail/qq_34195670/9592878
有兴趣的可以下载研究。
github地址:https://github.com/goingmyway1/-photoKit-
以上如有错误,请留言指正,谢谢!