参考资料
代码相关
使用<Photos/Photos.h>定制相册过程
1> 导入框架头:#import <Photos/Photos.h>
2> 获取所有胶卷名字
#pragma mark 获取所有的胶卷的名字
+ (NSMutableArray *)getAlbumObjects;
#pragma mark 获取胶卷的名字相关数据
+ (NSMutableArray *)getAlbumObjects {
NSMutableArray *array = [NSMutableArray array];
// 获得相机胶卷
PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
[array addObject:cameraRoll];
// 获得所有的自定义相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *assetCollection in assetCollections) {
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
if (assets.count) { // 如果相册里有图片,则添加到数组中
[array addObject:assetCollection];
}
}
return array;
}
3> 根据胶卷名字,获取所有的相册的封面图
#pragma mark 获取封面图片方法
+ (void)getCoverImageWith:(PHAssetCollection *)assetCollection withBlcok:(void(^)(UIImage *image))image;
#pragma mark 获取封面图片方法
+ (void)getCoverImageWith:(PHAssetCollection *)assetCollection withBlcok:(void(^)(UIImage *image))image {
PHFetchResult *assetResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
[[PHImageManager defaultManager] requestImageForAsset:assetResult.firstObject targetSize:CGSizeZero contentMode:PHImageContentModeDefault options:[PHImageRequestOptions new] resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
image(result);
}];
}
4> 获取每个相册的相片数量,用于显示在相册列表
#pragma mark 获取指定胶卷儿的照片的数量
+ (NSUInteger)getAlbumCountWith:(PHAssetCollection *)assetCollection;
#pragma mark 获取某胶卷儿的照片数量
+ (NSUInteger)getAlbumCountWith:(PHAssetCollection *)assetCollection {
// 获得某个相簿中的所有PHAsset对象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
return assets.count;
}
5> 获取单个相册的所有的缩略图,一次获取pageNumber张,并且可以通过页面滚动动态加载,这样的话就可以解决一次加载成百上千张造成的整个页面的卡顿甚至直接崩溃的问题
#pragma mark 滚动代理相关
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
/**
基本逻辑:
如果上一阶段的pageNumber中的图片添加完毕,每一组图片的高度大约为3000,
数值方向的偏移量大于3000,并且不是最后一张,就加载下一组的图片,大约一组
图片用零点几秒时间,无影响
*/
if (scrollView == self.collectionView) {
if (self.isAddPage && self.collectionView.contentOffset.y > self.currentPage*3000-700 && self.currentPage < self.totalPage ) {
self.isAddPage = NO;
// 获取单个相册中的200张图片
[AlbumTool getAlbumThumbnailWithAssetCollection:[self.albumsArray objectAtIndex:self.albumIndex] withPage:self.currentPage+1 andComplete:^(NSMutableArray *modelArray, NSInteger totalPhotos, NSInteger totalPage, NSInteger currentPage) {
[self.albumModelArray addObjectsFromArray:modelArray];
self.currentPage = currentPage; // 指定当前页数
self.totalPage = totalPage; // 获取相册所有页数
self.isAddPage = YES; // 如果有了返回数据,则可以进行添加了
// 新添加一步,对两个数据源进行比较,用于初始化显示
[self compareTwoModelArray]; // 可以一次匹配100张,这个也许可以
}];
}
}
}
#pragma mark 比较两个数组中元素
- (void)compareTwoModelArray {
/**
匹配规则:
新添加判断,一次只匹配比较pageNumber张
*/
NSLog(@"self.modelAdditionArray.count; ==== %lu",(unsigned long)self.modelAdditionArray.count);
NSInteger compareNumber = 0;
if (self.currentPage*PageNumber + PageNumber < self.albumModelArray.count) {
compareNumber = self.currentPage*PageNumber + PageNumber;
} else {
compareNumber = self.albumModelArray.count;
}
for (CertificateCellModel *model in self.modelAdditionArray) {
for (NSInteger i = self.currentPage*PageNumber; i < compareNumber; i ++) {
CertificateCellModel *modelOne = [self.albumModelArray objectAtIndex:i];
if ([model.localIdentifier isEqualToString:modelOne.localIdentifier]) {
NSLog(@"匹配到一张");
modelOne.cellImageType = CertificateCellImageSelect;
break;
}
}
}
// 在第一次添加的时候给一个第一次添加状态,其他的滑动启动这个方法,不会到顶部
if (self.isFirstAdd) {
// 数据加载完毕,将页面回到顶部
self.collectionView.contentOffset=CGPointMake(0, 0);
self.isFirstAdd = NO;
}
// 刷新数据
[self.collectionView reloadData];
}
获取缩略图方法:
可以传入页面数量和单个相册的相关数据,返回获取的所有图片数据,相册的总页数,相册总图片数,当前处在第几页。
#pragma mark 根据胶卷儿获取缩略图
+ (void)getAlbumThumbnailWithAssetCollection:(PHAssetCollection *)assetCollection withPage:(NSInteger)page andComplete:(void(^)(NSMutableArray *modelArray,NSInteger totalPhotos, NSInteger totalPage, NSInteger currentPage))modelArrayBlock;
#pragma mark 获取所有的缩略图
+ (void)getAlbumThumbnailWithAssetCollection:(PHAssetCollection *)assetCollection withPage:(NSInteger)page andComplete:(void(^)(NSMutableArray *modelArray,NSInteger totalPhotos, NSInteger totalPage, NSInteger currentPage))modelArrayBlock {
[self enumerateAssetsInAssetCollection:assetCollection original:NO withPage:page andComplete:^(NSMutableArray *modelArray,NSInteger totalPhotos, NSInteger totalPage, NSInteger currentPage) {
modelArrayBlock(modelArray,totalPhotos,totalPage,page);
}];
}
#pragma mark 缩略图的获取
+ (void)enumerateAssetsInAssetCollection:(PHAssetCollection *)assetCollection original:(BOOL)original withPage:(NSInteger)page andComplete:(void(^)(NSMutableArray *modelArray,NSInteger totalPhotos, NSInteger totalPage, NSInteger currentPage))modelArrayBlock {
NSLog(@"相簿名:%@", assetCollection.localizedTitle);
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步获得图片, 只会返回1张图片
options.synchronous = YES;
// 获得某个相簿中的所有PHAsset对象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
// NSLog(@"assets.count ========== %lu",(unsigned long)assets.count);
/**
如果我在这里添加一个GCD呢,会怎样呢?先试试
*/
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSMutableArray *modelArray = [NSMutableArray array];
NSUInteger totalPage = assets.count/PageNumber;
if (assets.count % PageNumber) {
totalPage ++;
}
for (NSInteger i = page*PageNumber; i < page*PageNumber + PageNumber; i ++) {
if (i >= assets.count) {
break;
} else {
PHAsset *asset = [assets objectAtIndex:assets.count-i-1];
// 是否要原图
CGSize size = original ? CGSizeMake(asset.pixelWidth, asset.pixelHeight) : CGSizeMake(125, 125);
// 从asset中获得图片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
/**
为了优化,直接将model在这里创建
*/
CertificateCellModel *model = [[CertificateCellModel alloc] init];
model.itemImage = result;
model.page = page;
model.assetCollection = assetCollection;
model.localIdentifier = asset.localIdentifier;
model.cellImageType = CertificateCellImageDeselect;
[modelArray addObject:model];
}];
}
}
dispatch_async(dispatch_get_main_queue(), ^{
modelArrayBlock(modelArray, assets.count, totalPage, page);
//回到主线程
});
});
}
6> 在定制相册中点击选中时,去获取原图,由于原图有时候会特别特别大,所以取原图时对原图进行处理,使其又相对清晰
#pragma mark 获取指定某张图片的原图
+ (void)photoWithAssetCollection:(PHAssetCollection *)assetCollection withLocalIdentifier:(NSString *)localIdentifier andPage:(NSInteger)page withBlcok:(void(^)(UIImage *bigImage))bigImage;
#pragma mark 获取单张原图
/**
基本逻辑:
首先知道相册,然后再知道相册中的第几个,那么直接匹配localIdentifier即可
*/
+ (void)photoWithAssetCollection:(PHAssetCollection *)assetCollection withLocalIdentifier:(NSString *)localIdentifier andPage:(NSInteger)page withBlcok:(void(^)(UIImage *bigImage))bigImage {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步获得图片, 只会返回1张图片
options.synchronous = YES;
// 获得某个相簿中的所有PHAsset对象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (NSInteger i = page*PageNumber; i < page*PageNumber + PageNumber; i ++) {
if (i >= assets.count) {
break;
} else {
PHAsset *asset = [assets objectAtIndex:assets.count-i-1];
// 是否要原图
if ([asset.localIdentifier isEqualToString:localIdentifier]) {
// 是否要原图
CGSize size = CGSizeMake(480.0, 640.0);
if (asset.pixelWidth > 480 || asset.pixelHeight > 640) {
size = CGSizeMake(480.0, 640.0);
} else {
size = CGSizeMake(asset.pixelWidth, asset.pixelHeight);
}
// 从asset中获得图片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
bigImage(result);
}];
break;
}
}
}
}
保存图片到相册
#pragma mark 保存图片
+ (void)saveImage:(UIImage *)image withLocalIdentifier:(void(^)(NSString *localIdentifier))localIdentifier;
#pragma mark 保存图片
+ (void)saveImage:(UIImage *)image withLocalIdentifier:(void(^)(NSString *localIdentifier))localIdentifier {
// UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
__block NSString *assetId = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ // 这个block里保存一些"修改"性质的代码
// 新建一个PHAssetCreationRequest对象, 保存图片到"相机胶卷"
// 返回PHAsset(图片)的字符串标识
assetId = [PHAssetCreationRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset.localIdentifier;
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (error) {
NSLog(@"保存图片到相机胶卷中失败");
return;
}
localIdentifier(assetId); // 将图片保存到相册中,并获取其唯一标识assetId及localIdentifier,用于后期的筛选
NSLog(@"成功保存图片到相机胶卷中");
}];
}