使用PhotoKit 搭建相册选择器(支持多选)

1. 闲谈

iOS8 以后苹果推出新的关于相册的框架-PhotoKit,相比较之前的AssetsLibrary 框架有了很大的提升,由于初次接触这个新的框架,也在网上查找了很多大神的博客资料,本文就浅谈一下自己对这个框架的理解。

2.介绍

PhotoKit 主要有PHAssetPHFetchOptionsPHFetchResultPHAssetCollectionPHImageManagerPHCollectionList几个重要的类。

PHAsset:代表照片库的一个资源 也就是具体的某一个照片或者视频。

PHFetchOptions: 获取资源的参数 可以为nil

PHFetchResult:表示一系列的资源结果集合,也可以是相册的集合 从PHCollection的方法中获得.

PHAssetCollection: PHCollection的子类,表示一个相册或者一个时刻(最近删除、收藏)

PHImageManager:用于处理资源的加载,加载图片的过程有缓存,可以使用 PHImageRequestOptions控制资源的输出尺寸等规格

PHCollectionList:表示一组PHCollection

3.开始搭建

  • 3.1 由于从相册获取照片之后需要展示,所有首先我们需要创建一个展示你选中照片的界面,因此我使用的是UICollectionView布局界面,并自定义了一个UICollectionViewCell 可以实现删除照片 命名为 - PhotoCell,如下所示:
#import 
#import 
@class PhotoCell;
@protocol PhotoCellDelegate 
/**删除照片的代理方法*/
-(void)deleteThePhotoForCell:(PhotoCell *)cell  deleteBtn:(UIButton *)btn;
@end

@interface PhotoCell : UICollectionViewCell
/**图片视图*/
@property(nonatomic,strong)UIImageView *photoView;
/**删除按钮*/
@property(nonatomic,strong)UIButton *deleteBTn;
/**代理*/
@property(nonatomic,weak) id  delegate;
@end
  • 3.2 创建一个管理获取相册资源的工具类 - YHPhotosData,使用这个工具类实现以下功能:获取所有相册列表、获取某一个相册中的照片资源、 将具体某一个照片资源转化为照片。
    YHPhotosData.h文件中
#import 
#import //系统照片的框架
@interface YHPhotosData : NSObject
//获取所有的相册集
+(NSMutableArray *)getAllPhotoListData;
//获取某一个相册的所有资源
+(NSMutableArray *)getPhotosForPHAssetCollection:(PHAssetCollection *)collection;
//从相册的某一个照片资源获取一张高清照片
-(void)getImageObject:(id)set Complection:(void(^)(UIImage *photo,BOOL isDegraded))complection;
@end

YHPhotosData.m文件中

+(NSMutableArray *)getAllPhotoListData{
   NSMutableArray *dataArray = [NSMutableArray array];
   //1.0列出所有智能相册
   PHFetchResult *samrtResult  = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
 for(int i = 0 ;i
+(NSMutableArray *)getPhotosForPHAssetCollection:(PHAssetCollection *)collection{
    NSMutableArray *photosArray = [NSMutableArray array];
    //1.获取了结果集
    PHFetchResult *photosResult = [PHAsset fetchAssetsInAssetCollection:collection options:nil];  
    //2.便利结果集 取出具体某一张图片资源  添加在数组中  
    for(PHAsset *set  in  photosResult){
        if(set.mediaSubtypes == PHAssetMediaSubtypeNone){   
            [photosArray addObject:set];
        }    
    }
    return  photosArray;
}
-(void)getImageObject:(id)set Complection:(void (^)(UIImage *, BOOL))complection
{
    if ([set isEqual:[PHAsset class]]){     
        PHAsset *photoSet = set;
        CGFloat mainWidth = [UIScreen mainScreen].bounds.size.width;
       //1.0算出照片资源自身的比例
        CGFloat setScale = photoSet.pixelWidth/photoSet.pixelHeight;
        //1.1 获取屏幕比例
        //屏幕分辨率 scale = 1 代表 分辨率是320 * 480; =2 代表 分辨率是 640 * 960; = 3 代表 分辨率是 1242 * 2208
        CGFloat scale = [UIScreen mainScreen].scale;
        //1.2计算照片在不同屏幕上的像素   
        CGFloat pixWidth = mainWidth * scale;
        //1.3根据图片自身比例计算照片在屏幕上的高
        CGFloat pixheight = mainWidth/setScale;       
        /**
         *  PHImageManager 是通过请求的方式拉取图像,并可以控制请求得到的图像的尺寸、剪裁方式、质量,缓存以及请求本身的管理(发出请求、取消请求)等
         *
         *  @param pixelWidth 获取图片的宽
         *  @param pixelHeight 获取图片的高
         *  @param contentMode 图片的剪裁方式
         *
         *  @return
         */    
     [[PHImageManager defaultManager] requestImageForAsset:photoSet targetSize:CGSizeMake(pixWidth, pixheight) 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]);
             }
         }
     }]; 
 }
}
  • 3.3 工具类写完之后,接下来开始创建相册列表控制器 PhotosListVC 用来展示所有的相册列表,同时自定义Cell(我这里定义的是PhotoListCell)用来显示每个相册。cell中显示的照片就是该相册中所有照片中的最后一张。
    PhotoListCell 定义非常简单,我在这里就不过多叙述了.
/**图片视图*/
@property(nonatomic,strong)UIImageView *photoView;
/**标题*/
@property(nonatomic,strong)UILabel *title;

这里比较重要的一个方法就是 给cell设置默认数据。既相册的标题 以及显示的照片(最后一张).

///设置数据
-(void)getImageForAssetCollection:(PHAssetCollection *)coll{  
    //获取该相册最后一张照片资源
    PHAsset *set = [[YHPhotosData getPhotosForPHAssetCollection:coll] lastObject] ;   
    //转化为照片  并设置数据  (由于相册可能没有照片需要判断一下,给一张默认的照片)          
    [[PHImageManager defaultManager]requestImageForAsset:set targetSize:self.photoView.frame.size contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        if (result == nil) {
            self.photoView.image = [UIImage imageNamed:@"no_data"];
        }else {       
            self.photoView.image = result;
        }
    }];
     self.title.text = coll.localizedTitle;
}
  • 3.4 创建展示相册所有照片的控制器PhotoShowVC,并自定义个Cell展示照片,这里我自己定义的是PhotosShowCell.
    PhotosShowCell.h
#import 
#import 
//获取点击的照片
typedef void (^PhotosShowCellBlock)(UIImage *image);
@interface PhotosShowCell : UICollectionViewCell
/**选择按钮*/
@property(nonatomic,strong)UIButton *selectBTn;
//获取点击的那个照片blcok
@property(nonatomic,copy)PhotosShowCellBlock cellBlock;
//设置数据
-(void)setPhotoForPHAsset:(PHAsset *)set;
@end

PhotosShowCell.m

//设置cell数据 传递过来的都是一张照片资源  不是照片 需要转化
-(void)setPhotoForPHAsset:(PHAsset *)set{
    [[PHImageManager defaultManager]requestImageForAsset:set targetSize:self.photoView.frame.size contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {  
        if (result) {      
            // 排除取消,错误,低清图三种情况,即已经获取到了高清图
            BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey]);
            if (downloadFinined) {     
                self.photoView.image =result;   
                if (self.cellBlock) {
                  //获取点击的照片
                    self.cellBlock(result);
                }
            }          
        }else {
            self.photoView.image = [UIImage imageNamed:@"no_data"];
        }     
    }];
}

在控制器PhotoShowVC创建一个可变数组selectImageArray存放选中的所有照片,在cell的点击方法中 执行cell的block方法获取到点击的照片, 并存放到数组selectImageArray中,同时改变cell上按钮的状态。

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    PhotosShowCell *cell  = (PhotosShowCell *)[collectionView cellForItemAtIndexPath:indexPath];
    if (cell.selectBTn.selected) {
        cell.selectBTn.selected = NO;  
        [cell.selectBTn setImage:[UIImage imageNamed:@"select_no"] forState:UIControlStateNormal];
        [self.selectImageArray removeObjectAtIndex:indexPath.row];
    }else {
        cell.selectBTn.selected = YES;
        [cell.selectBTn setImage:[UIImage imageNamed:@"select_yes"] forState:UIControlStateNormal];  
        [cell setPhotoForPHAsset:self.imageArray[indexPath.row]];
         cell.cellBlock = ^(UIImage *image) {
         [self.selectImageArray addObject:image];
        };   
    }
}

然后在控制器PhotoShowVC创建完成、预览按钮以及定义一个返回首页并传递照片到首页的Blcok ,当选择结束点击完成时候,执行Blcok 将选中的图片数组传递到首页。

-(void)clickBtn:(UIButton *)sender{
    if (self.selectImageArray.count > 0) {
        if (self.block) {   
           // [self.navigationController popViewControllerAnimated:YES];
            self.block(self.selectImageArray);
        }
    }else {
        NSLog(@"还没选择图片");
    }
}

预览界面就不在过多叙述了,非常简单,详情看Demo。

你可能感兴趣的:(使用PhotoKit 搭建相册选择器(支持多选))