使用框架:PhotoKit (8.0后可使用) 需添加 Photos.framework库 并在使用的控制器中添加头文件:#import <Photos/Photos.h>
AssetsLibrary框架在9.0后已废弃。
- PHAsset: 照片库中的一个资源 (一个照片或视频)。
- PHAssetCollection: 一个相册(里面包含照片或视频等)。其常用属性有,localizedTitle:相册名字(最近添加,屏幕快照...)
- PHFetchResult: 一系列资源的集合,或者相册的集合。
- PHFetchOptions: 获取资源时的参数,传nil,即系统默认值。
- PHImageRequestOptions:控制加载图片时的参数。
- PHImageManager: 用于处理资源的加载,加载图片的过程带有缓存处理,可以通过传入一个 PHImageRequestOptions 控制资源的输出尺寸等规格。
直接上代码:
//获取所有的系统相册
PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
//将smartAlbums中的相册添加到数组中(最近添加,相机胶卷,视频...)
for (PHAssetCollection *collection in smartAlbums) {
//如果不想显示 ‘最近添加’ ‘收藏’等 可以这样做
if (collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumRecentlyAdded || collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumFavorites) {
continue;
}
//遍历所有相册,只显示有视频或照片的相册
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d || mediaType == %d", PHAssetMediaTypeImage,PHAssetMediaTypeVideo];
//按创建时间排序
fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
PHFetchResult *assetResults = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptions];
if (assetResults.count>0) {
[self.albumsArray addObject:collection];
}
}
此处获取的是系统自己生成的相册,
获取从电脑同步过来的相册:
PHFetchResult *PCAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumSyncedAlbum options:nil];
获取自己创建的相册:
PHFetchResult *topLevelUserCollections = [PHCollection fetchTopLevelUserCollectionsWithOptions:nil];
关于PHAssetCollectionType 与 PHAssetCollectionSubtype :
enum PHAssetCollectionType : Int {
case Album //从 iTunes 同步来的相册,以及用户在 Photos 中自己建立的相册
case SmartAlbum //经由相机得来的相册
case Moment //Photos 为我们自动生成的时间分组的相册
}
enum PHAssetCollectionSubtype : Int {
case AlbumRegular //用户在 Photos 中创建的相册,也就是我所谓的逻辑相册
case AlbumSyncedEvent //使用 iTunes 从 Photos 照片库或者 iPhoto 照片库同步过来的事件。然而,在iTunes 12 以及iOS 9.0 beta4上,选用该类型没法获取同步的事件相册,而必须使用AlbumSyncedAlbum。
case AlbumSyncedFaces //使用 iTunes 从 Photos 照片库或者 iPhoto 照片库同步的人物相册。
case AlbumSyncedAlbum //做了 AlbumSyncedEvent 应该做的事
case AlbumImported //从相机或是外部存储导入的相册,完全没有这方面的使用经验,没法验证。
case AlbumMyPhotoStream //用户的 iCloud 照片流
case AlbumCloudShared //用户使用 iCloud 共享的相册
case SmartAlbumGeneric //文档解释为非特殊类型的相册,主要包括从 iPhoto 同步过来的相册。由于本人的 iPhoto 已被 Photos 替代,无法验证。不过,在我的 iPad mini 上是无法获取的,而下面类型的相册,尽管没有包含照片或视频,但能够获取到。
case SmartAlbumPanoramas //相机拍摄的全景照片
case SmartAlbumVideos //相机拍摄的视频
case SmartAlbumFavorites //收藏文件夹
case SmartAlbumTimelapses //延时视频文件夹,同时也会出现在视频文件夹中
case SmartAlbumAllHidden //包含隐藏照片或视频的文件夹
case SmartAlbumRecentlyAdded //相机近期拍摄的照片或视频
case SmartAlbumBursts //连拍模式拍摄的照片,在 iPad mini 上按住快门不放就可以了,但是照片依然没有存放在这个文件夹下,而是在相机相册里。
case SmartAlbumSlomoVideos //Slomo 是 slow motion 的缩写,高速摄影慢动作解析,在该模式下,iOS 设备以120帧拍摄。不过我的 iPad mini 不支持,没法验证。
case SmartAlbumUserLibrary //这个命名最神奇了,就是相机相册,所有相机拍摄的照片或视频都会出现在该相册中,而且使用其他应用保存的照片也会出现在这里。
case Any //包含所有类型
}
获取到各种相册后,就要获取相册内的照片或视频等资源了。
这里只获取照片和视频,所以用PHFetchOptions进行过滤。
//获取此相册内所有资源(PHAsset)
PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init];
fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType == %d || mediaType == %d", PHAssetMediaTypeImage,PHAssetMediaTypeVideo];
PHFetchResult *assetResults = [PHAsset fetchAssetsInAssetCollection:self.iAssetCollection options:fetchOptions];
for (PHAsset *asset in assetResults) {
[self.iAssetArray addObject:asset];
}
到此为止,我们已经获取到需要的相册及各相册内的资源。
接下来,讲解如何从PHAsset获取具体的图片/视频 信息。
PhotoKit引用了PHImageManager获取图片,使用该类对象调用下面函数 拉取资源
拉取资源时用到了两个函数:
- (PHImageRequestID)requestImageForAsset:(PHAsset *)asset targetSize:(CGSize)targetSize contentMode:(PHImageContentMode)contentMode options:(nullable PHImageRequestOptions *)options resultHandler:(void (^)(UIImage *__nullable result, NSDictionary *__nullable info))resultHandler;
此函数的 resultHangler中直接返回了UIImage。
- asset:上面获取的PHAsset对象
- targetSize:需要获取的图片尺寸,如果输入的尺寸大于资源原图的尺寸,则只返回原图。需要注意在 PHImageManager 中,所有的尺寸都是用 Pixel 作为单位(Note that all sizes are in pixels),因此这里想要获得正确大小的图像,需要把输入的尺寸转换为 Pixel。如果需要返回原图尺寸,可以传入 PhotoKit 中预先定义好的常量?PHImageManagerMaximumSize,表示返回可选范围内的最大的尺寸,即原图尺寸。
- contentMode:图像的剪裁方式,与UIView 的 contentMode 参数相似,控制照片应该以按比例缩放还是按比例填充的方式放到最终展示的容器内。注意如果 targetSize 传入PHImageManagerMaximumSize,则 contentMode 无论传入什么值都会被视为?PHImageContentModeDefault。
- options:在下面详解.
- resultHandler: 存放着需要的UIImage及其它信息。
- (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset options:(nullable PHImageRequestOptions *)options resultHandler:(void(^)(NSData *__nullable imageData, NSString *__nullable dataUTI, UIImageOrientation orientation, NSDictionary *__nullable info))resultHandler;
此函数的 resultHangler中直接返回了NSData。
这两个函数中都使用了PHImageRequestOptions 参数;
PHImageRequestOptions属性如下:
synchronous:指定请求是否同步执行。如果为YES,或许会出现卡顿现象.
resizeMode:对请求的图像怎样缩放。有三种选择:None,不缩放;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。
deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。
这个属性只有在 synchronous 为 true 时有效。
normalizedCropRect:用于对原始尺寸的图像进行裁剪,基于比例坐标。只在 resizeMode 为 Exact 时有效。
若要使上面两个函数中的targetSize参数生效,则PHImageRequestOptions属性resizeMode必须为Exact.
拉取图片的具体详情可以参考这篇博文