iOS中自定义相册(上)
2016-10-31 本文已影响144人
傲视苍穹
第一首先创建一个管理相片的单列类 (必须导入相册对应的类库 @import AssetsLibrary;
@import UIKit;
)
从ALAsset对象中获取UIImage对象 [UIImage imageWithCGImage:asset.aspectRatioThumbnail]]
- 需要定义必要的一些属性和回调Block。
//回调Block
typedef void(^ALAssetGroupBlock)(NSArray <ALAssetsGroup *> * groups);
typedef void(^ALAssetPhotoBlock)(NSArray <ALAsset *> * photos);
typedef void(^ALAssetFailBlock)(NSString * error);
//属性
@property (nonatomic, strong) ALAssetsLibrary * library;//相册库
@property (nonatomic, copy) ALAssetGroupBlock block;
@property (nonatomic, strong) NSMutableArray <ALAssetsGroup *> * groups;//存放所有照片组的数组对象
@property (nonatomic, strong) NSMutableArray <ALAsset *> * photos;//存放所有照片的数组对象
- 创建单列类和初始化属性。
-(instancetype)init
{
if (self = [super init])
{
//实例化库对象
self.library = [[ALAssetsLibrary alloc]init];
//初始化数组
self.groups = [NSMutableArray arrayWithCapacity:0];
self.photos = [NSMutableArray arrayWithCapacity:0];
}
return self;
}
+(instancetype)shareInstance
{
static RTPhotoManager * photoManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
photoManager = [[RTPhotoManager alloc]init];
});
return photoManager;
}
- 创建组名叫做title的相片组
- (void)createGroupWithTitle:(NSString *)title
{
//开始创建
[self.library addAssetsGroupAlbumWithName:title resultBlock:^(ALAssetsGroup *group) {
NSLog(@"创建成功!");
} failureBlock:^(NSError *error) {
NSLog(@"error = %@",error.localizedDescription);
}];
}
- 判断是否包含相机胶卷
- (BOOL)containCameraRoll:(ALAssetsGroup *)group
{
//如果是相机胶卷,放到第一位,这里只适配英文以及中文
NSString * nameCN = NSLocalizedString([group valueForProperty:ALAssetsGroupPropertyName], @"");
NSString * nameEN = NSLocalizedString([group valueForProperty:ALAssetsGroupPropertyName], @"");
//对当前组数进行排序
if ([nameCN isEqualToString:@"相机胶卷"]
|| [nameEN isEqualToString:@"Camera Roll"])
{
//修改变量
return YES;
}
return NO;
}
- 读取相册的所有组
-(void)readAllPhotoGroups:(ALAssetGroupBlock)groupBlock Fail:(ALAssetFailBlock)failBlock CameraRollHandel:(void (^)(void))cameraRollHandle
{
//删除之前存的所有组
[self.groups removeAllObjects];
__block __weak typeof(self) copy_self = self;
//开始遍历
[self.library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
//如果返回的组存在
if (group)
{
//对group进行过滤,只要照片
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
//添加数据
[copy_self.groups addObject:group];
//进行顺序判断
if([self containCameraRoll:group] == true)
{
//删除当前位置的数组
[self.groups removeObjectAtIndex:self.groups.count - 1];
[self.groups insertObject:group atIndex:0];
}
//回调数据
groupBlock([NSArray arrayWithArray:copy_self.groups]);
//进行序列后的回调
if([self containCameraRoll:group] == true)
cameraRollHandle();
}
} failureBlock:^(NSError *error) {
//失败回调
failBlock(error.localizedDescription);
}];
}
- 打开相片组
-(void)openPhotosGroup:(ALAssetsGroup *)assetsGroup Success:(ALAssetPhotoBlock)successBlock Fail:(ALAssetFailBlock)failBlock
{
//删除所有的照片对象
[self.photos removeAllObjects];
//避免强引用
__block __weak typeof(self) copy_self = self;
//获取当前组的url数据
NSURL * url = [assetsGroup valueForProperty:ALAssetsGroupPropertyURL];
//打开向前的组
[self.library groupForURL:url resultBlock:^(ALAssetsGroup *group) {
[copy_self photosInGroups:group Block:successBlock];
} failureBlock:^(NSError *error) {
//失败的回调
failBlock(error.localizedDescription);
}];
}
- 获取所有的照片对象
- (void)photosInGroups:(ALAssetsGroup *)group Block:(ALAssetPhotoBlock)photoBlock
{
//开始读取
[group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) {
//如果不为空或者媒体为图片
if (result != nil && [[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto])
{
//添加数据
[self.photos addObject:result];
//数目达标后统一进行回调
if (index == group.numberOfAssets - 1)
{
//回调
photoBlock([NSArray arrayWithArray:self.photos]);
}
}
}];
}
第二就用 UICollectionView 展示相册中的图片
- 首先获得相册管理的单列对象。
self.photoManager = [RTPhotoManager shareInstance];
- 从单列对象里取出相册中所有的图片组。
- (void)requestPhotoGroup
{
//避免强引用
__block __weak typeof(self) copy_self = self;
//开始请求
[self.photoManager readAllPhotoGroups:^(NSArray<ALAssetsGroup *> *groups) {
copy_self.groupArray = groups;
} Fail:^(NSString *error) {} CameraRollHandel:^{
[self loadPhotosWithGroup:self.groupArray.firstObject];
self.navigationItem.title = [self.groupArray.firstObject valueForProperty:ALAssetsGroupPropertyName];
}];
}
- 然后从每个图片组中取出对于的图片。
- (void)loadPhotosWithGroup:(ALAssetsGroup *)assetsGroup
{
[self.photoManager openPhotosGroup:assetsGroup Success:^(NSArray<ALAsset *> *photos) {
self.photos = [NSMutableArray arrayWithArray:photos];
//刷新
[self.collectionView reloadData];
//滚动到最后一个的位置
[self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:self.photos.count - 1 inSection:0] atScrollPosition:UICollectionViewScrollPositionBottom animated:false];
} Fail:^(NSString *error) {
NSLog(@"error = %@",error);
}];
}
- 最后就是把每组的图片展示在UICollectionView上。
注:是由中心点取正方形范围的图片(可以用于展示的缩略图;而用ALAsset 对象取得thumbnail
缩略图比较模糊)
- (UIImage*)getThumbnailImage:(UIImage *)image {
float imgwidth = image.size.width;
float imgheight = image.size.height;
float viewwidth = 0;
float viewheight = 0;
if (MAX(imgwidth, imgheight) == imgheight) {
viewwidth = imgwidth;
viewheight = imgwidth;
}else{
viewwidth = imgheight;
viewheight = imgheight;
}
CGRect rect = CGRectMake((imgwidth-viewwidth)/2, (imgheight-viewheight)/2, viewwidth, viewheight);
CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
CGRect smallBounds = CGRectMake(0, 0, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef));
UIGraphicsBeginImageContext(smallBounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, smallBounds, subImageRef);
UIImage* smallImage = [UIImage imageWithCGImage:subImageRef];
UIGraphicsEndImageContext();
return smallImage;
}