个人相册开发(10)

一.写一个类用于显示相机和系统相册界面

在plist文件设置相应的权限框文本

1.创建一个XLImagePicker类,并定义一个block用于回调数据到类方法创建的地方

//定义一个block用于回调数据
typedef void(^PickingBlock)(NSArray *pictureModelArray);

@interface XLImagePicker : NSObject

//显示挑选界面
+(void)showPickerWithType:(ActionType)type handle:(PickingBlock)block;

@end

2.让该类遵从系统以及我们自身创建的协议,实现相应的代理方法

@interface XLImagePicker()

//定义一个变量用于保存block
@property (nonatomic, copy) PickingBlock PickerBlock;

@end

//全局化,便于操作
XLImagePicker *picker = nil;

@implementation XLImagePicker

#pragma mark -------显示挑选界面 ---------
+(void)showPickerWithType:(ActionType)type handle:(PickingBlock)block{
    
    //初始化一个实例
    picker = [XLImagePicker new];
    
    //保存block
    picker.PickerBlock = block;
    
    //判断是否授权
    if ([XLSystemAlbumManager isXLHaveAuthorityWithType:type]) {
        
        //判断显示什么挑选界面
        if (type == ActionTypeLibrary) {
            
        //授权点击
        [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
            if(status == PHAuthorizationStatusAuthorized) {
                
                //用户点击允许
                
                //系统相册
                [picker showSystemAlbum];
            } else {
                
                // 用户点击 不允许访问
            }
        }];
            
            
        }else{
            
            //读取设备授权状态
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                if (granted) {
                    
                    //允许了
                    
                    //相机
                    [picker showCamera];
                }
            }];
        }
        
    }else{
        
        //警告框
        XLActionViewController *myAlert = [XLActionViewController showAlertControllerWithType:AlertTypeAlert AndName:@"请设置相关权限"];
        
        //解决循环引用的可能
        __block typeof(myAlert) weakAlert = myAlert;
        
        //移除
        [myAlert setCancelblock:^{
            [weakAlert dismiss];
        }];
    }
}

#pragma mark -------相册 ---------
-(void)showSystemAlbum{

    //创建系统相册界面
    XLSystemAlbumController *sac = [XLSystemAlbumController new];
    
    //设置系统相册界面遵循代理对象
    sac.delegate = self;
    
    //监听设置代理的消息
    [[NSNotificationCenter defaultCenter] addObserverForName:kPictureSetDelegateNotificationName object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull note) {
        
        //获得界面
        XLSystemPictureController *spc = (XLSystemPictureController *)note.object;
        
        //设置系统相册内部界面遵循代理对象
        spc.delegate = self;
    }];

    //弹出相册
    
    //中途需要导航栏
    XLNavigationController *mynav = [[XLNavigationController alloc] initWithRootViewController:sac];
    
    //找到当前界面的视图
    //1.通过窗口找到当前的界面
    XLNavigationController *nav =  (XLNavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
    //2.找到导航栏控制器当前显示的界面
    UIViewController *pictureView = nav.visibleViewController;
    
    //跳转
    [pictureView presentViewController:mynav animated:YES completion:nil];
}

#pragma mark -------相机 ---------
-(void)showCamera{
    //先判断相机是否可用
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

        //创建相机
        UIImagePickerController *ipc = [[UIImagePickerController alloc] init];

        //设置来源
        ipc.sourceType = UIImagePickerControllerSourceTypeCamera;

        //支持的类型
        ipc.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];

        //设置代理
        ipc.delegate = picker;

        //弹出相机
        
        //中途需要导航栏
        XLNavigationController *mynav = [[XLNavigationController alloc] initWithRootViewController:ipc];

        //找到当前界面的视图
        //1.通过窗口找到当前的界面
        XLNavigationController *nav =  (XLNavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
        //2.找到导航栏控制器当前显示的界面
        UIViewController *pictureView = nav.visibleViewController;

        //跳转
        [pictureView presentViewController:mynav animated:YES completion:nil];

    }else{
        
        //警告框
        XLActionViewController *myAlert = [XLActionViewController showAlertControllerWithType:AlertTypeAlert AndName:@"你的摄像头不可用"];
        
        //解决循环引用的可能
        __block typeof(myAlert) weakAlert = myAlert;
        
        //移除
        [myAlert setCancelblock:^{
            [weakAlert dismiss];
        }];
        
    }
}

#pragma mark -------相册的代理方法 ---------
//Cancel按钮被点击了
-(void)XLImagesPickerControllerDidCancel:(XLSystemAlbumController *)picker{
    
    //移除视图
    [picker dismissViewControllerAnimated:YES completion:nil];
}

//Done按钮被点击了
-(void)XLImagesPickerController:(XLSystemPictureController *)picker didFinishedPickingWithInfo:(NSArray *)info{
    
    //移除视图
    [picker dismissViewControllerAnimated:YES completion:nil];
    
  
}

#pragma mark -------相机的代理方法 ---------
//点击Cancel按钮
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    
    //移除imagePickerController
    [picker dismissViewControllerAnimated:YES completion:nil];
}

//内容被封装在info里面
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    
    //移除imagePickerController
    [picker dismissViewControllerAnimated:YES completion:nil];
}

@end

3.由于系统相册内部界面不是在当前界面创建的,而是和当前界面隔了一层界面,我们通过消息通知设置代理对象,在StringConstants中加入消息,监听消息,接受就好

//系统相册内部界面设置代理的消息
#define kPictureSetDelegateNotificationName @"kPictureSetDelegateNotificationName"

二.完善XLPictureCell的显示

1..h文件里面定义一个变量接受数据显示信息,还要定义一个变量接受状态,加上之前的接受Cell类型的变量,最后添加一个更改按钮的状态的接口

@interface XLPictureCell : UICollectionViewCell

//接受外界传递过来的数据
@property (nonatomic,strong) XLPictureModel *model;

//接受外界传递过来的Cell类型
@property (nonatomic,assign) CellType type;

/**接受外界传递过来的编辑状态*/
@property (nonatomic,assign) BOOL isEditing;

//更改勾选按钮的状态
- (void)changeStatus:(BOOL)status;

@end

2.重写type的set方法,确定勾选按钮和添加按钮是否需要添加

#pragma mark -------重写type的set方法 ---------
-(void)setType:(CellType)type{
    
    _type = type;
    
    //判断type的类型
    if (type == CelllTypeAdd) {
        //隐藏勾选按钮
        self.selectImageView.hidden = YES;
        //显示添加按钮
        self.addImageView.hidden = NO;
    }else if(type == CellTypeSystem){
        //显示勾选按钮
        self.selectImageView.hidden = NO;
        //隐藏添加按钮
        self.addImageView.hidden = YES;
    }else{
        //隐藏勾选按钮
        self.selectImageView.hidden = YES;
        //隐藏添加按钮
        self.addImageView.hidden = YES;
    }
}

3.重写isEditing的set方法,判断勾选按钮是否需要显示

#pragma mark -------重写isEditing的set方法 ---------
-(void)setIsEditing:(BOOL)isEditing{
    
    _isEditing = isEditing;
    
    if (isEditing == YES) {
        //显示勾选按钮
        self.selectImageView.hidden = NO;
    }else{
        //隐藏勾选按钮
        self.selectImageView.hidden = YES;
    }
}

4.实现勾选按钮状态改变的方法

#pragma mark -------更改勾选按钮的状态 ---------
- (void)changeStatus:(BOOL)status{
    
    if (status == YES) {
        
        //选中
        self.selectImageView.image = [UIImage imageNamed:@"selected_selected"];
    }else{
        
        //未选中
        self.selectImageView.image = [UIImage imageNamed:@"selected_normal"];
    }
}

5.重写model的set方法,让Cell显示数据

#pragma mark -------重写model的set方法一有数据就赋值 ---------
-(void)setModel:(XLPictureModel *)model{
    
    _model = model;

    //缩略图
    self.iconImageView.image = model.iconImage;
    
    
    //判断时长
    if (model.duration > 0) {
        //显示视频时间
        self.timeBgView.hidden = NO;
        self.timeLabel.text = model.duration;
    }else{
        //隐藏视频时间
        self.timeBgView.hidden = YES;
    }
    
    //selected的视图 默认不选中
    [self changeStatus:self.isSelected];
}

三.系统相册界面显示跳转到个人相册界面

1.显示:我们通过XLSystemAlbumManager的getAllSystemAlbumArray方法获得所有系统相册的模型数据,并显示数据

#pragma mark -------类方法创建 ---------
+(XLAlbumTableView *)showAlbumView:(CGRect)frame ViewType:(ViewType)type Array:(NSMutableArray *)modelsArray superView:(UIView *)sView{
    
    //创建
    XLAlbumTableView *atv = [[XLAlbumTableView alloc] initWithFrame:frame];
    
    //保存类型
    atv.type = type;
    
    //保存数据
    atv.modelsArray = modelsArray;
   
    //显示
    [sView addSubview:atv];
    
    return atv;
}

#pragma mark -------重写initWithFrame方法 布局 ---------
-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        
        //创建tableView
        self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
        
        //设置代理
        _tableView.delegate = self;
        _tableView.dataSource = self;
        
        //去除纵向滚动条
        _tableView.showsVerticalScrollIndicator = NO;
        
        //设置分割线风格
        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
        
        //编辑模式下是否允许多选
        _tableView.allowsMultipleSelectionDuringEditing = YES;
        
        //显示
        [self addSubview:_tableView];
        
        //注册cell
        [_tableView registerNib:[UINib nibWithNibName:@"XLAlbumCell" bundle:nil] forCellReuseIdentifier:@"cellID"];
        
    }
    return self;
}

#pragma mark -------UITableView ---------
//配置有多少个相册
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    
    return self.modelsArray.count;
}

//配置每个相册具体显示什么内容
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    //创建cell
    XLAlbumCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
    
    //传递数据
    cell.model = self.modelsArray[indexPath.row];
    
    return cell;
}

//配置cell的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    return 100;
}

//某个cell被点击了
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    //判断编辑状态
    if (self.tableView.editing) {
        
        //编辑状态
        
        //告诉manager某一个被点击了
        [[XLAlbumManager sharedManager] albumEditingStatusChanged:YES index:indexPath.row];
    }else{
        
        //正常状态
        
        //1.取消选中
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        
        //判断是什么相册
        if (_type == ViewTypePerson) {
            
            //个人相册
            
        }else{
            
            //系统相册

        }
    }
}

//某个cell取消选中了
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    //判断是不是编辑状态
    if (self.tableView.editing) {
        
        //告诉manager某一个取消点击了
        [[XLAlbumManager sharedManager] albumEditingStatusChanged:NO index:indexPath.row];
    }
}

//设置tableView的编辑状态 左边显示的样式 delete insert none
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    //可以勾选的样式
    return UITableViewCellEditingStyleInsert | UITableViewCellEditingStyleDelete;
}

@end

2.跳转:因为我们的XLAlbumTableView既会用来创建个人相册界面,又会被用来创建系统相册界面,在cell被点击的方法里面判断是哪一种情况被点击。当是系统相册时,创建系统相册内部界面并跳转,此时,该类被创建,就可以向XLImagePicker中发送消息,设置其代理对象

//某个cell被点击了
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    
    //判断编辑状态
    if (self.tableView.editing) {
        
        //编辑状态
        
        //告诉manager某一个被点击了
        [[XLAlbumManager sharedManager] albumEditingStatusChanged:YES index:indexPath.row];
    }else{
        
        //正常状态
        
        //1.取消选中
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        
        //判断是什么相册
        if (_type == ViewTypePerson) {
            
            //个人相册
        }else{
            
            //系统相册
            
            //2.进入下一个界面
            XLSystemPictureController *svc = [XLSystemPictureController new];
            
            //设置代理对象
            [[NSNotificationCenter defaultCenter] postNotificationName:kPictureSetDelegateNotificationName object:svc];
            
            //3.传递数据
            svc.albumModel = self.modelsArray[indexPath.row];
            
            //4.找到当前的导航栏控制器
            XLNavigationController *nav = (XLNavigationController *)[UIApplication sharedApplication].keyWindow.rootViewController;
            
            //5.找到导航栏控制器的顶部视图
            XLPersonPictureController *ppc = (XLPersonPictureController *)nav.topViewController;
            
            //6.找到顶部视图present的视图
            XLNavigationController *navPresent = (XLNavigationController *)ppc.presentedViewController;
            
            //7.跳转
            [navPresent pushViewController:svc animated:YES];
        }
    }
}

四.系统相册内部界面显示

我们通过XLSystemAlbumManager的getAllPictureInAssetCollection方法获得某个系统相册里面的资源模型数据,并显示数据

@interface XLPictureCollectionView ()

/**接受传递的类型*/
@property (nonatomic,assign) ViewType type;

/**接受传递的相册模型*/
@property (nonatomic,strong) XLAlbumModel *albumModel;

/**保存我们显示的资源模型*/
@property (nonatomic,strong) NSMutableArray *pictureModelArray;

/**属性化的collectionView*/
@property (nonatomic,strong) UICollectionView *collectionView;

/**记录编辑状态*/
@property (nonatomic,assign) BOOL isEditing;

@end

@implementation XLPictureCollectionView

#pragma mark -------类方法创建 ---------
+(XLPictureCollectionView *)showCollectionView:(CGRect)frame ViewType:(ViewType)type Model:(XLAlbumModel *)model toView:(UIView *)superView{
    
    //创建
    XLPictureCollectionView *pcv = [[XLPictureCollectionView alloc] initWithFrame:frame];
    
    //保存类型
    pcv.type = type;
    
    //保存传递过来的相册模型
    pcv.albumModel = model;
    
    //保存数据
    if (type == ViewTypeSystem) {
        
        //加载系统相册的图片
        pcv.pictureModelArray = [[XLSystemAlbumManager sharedSystemAlbum] getAllPictureInAssetCollection:model.assetCollection ascending:NO];
    }else{
        //加载个人相册的图片
    }
    
    //显示
    [superView addSubview:pcv];
    
    return pcv;
}

#pragma mark -------重写initWithFrame方法 布局 ---------
-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        
        //当前视图的背景颜色
        self.backgroundColor = [UIColor clearColor];
        
        //创建布局对象
        UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
        
        //每一个item的大小
        layout.itemSize = CGSizeMake(kSize, kSize);
        
        //竖向最小间距
        layout.minimumLineSpacing = 1;
        
        //横向最小间距
        layout.minimumInteritemSpacing = 0.001f;
        
        //layout.sectionInset = UIEdgeInsetsMake(5, 5, 5,5);
        
        //创建collectionView
        self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height) collectionViewLayout:layout];
        
        //collectionView的背景颜色
        _collectionView.backgroundColor = [UIColor clearColor];
        
        //设置代理
        _collectionView.delegate = self;
        _collectionView.dataSource = self;
        
        //显示
        [self addSubview:_collectionView];
        
        //注册
        [_collectionView registerNib:[UINib nibWithNibName:@"XLPictureCell" bundle:nil]  forCellWithReuseIdentifier:@"cellID"];
    }
    return self;
}

#pragma mark -------UICollectionView代理方法 ---------
//返回item的数量
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    
    //判断是什么类型
    if (self.type == ViewTypePerson) {
        
        //个人相册
        return 1;
    }else{
        
        //系统相册
        return self.pictureModelArray.count;
    }
}

//每个cell显示什么
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    
    //创建
    XLPictureCell *cell;
    
    //判断类型
    if (self.type == ViewTypePerson) {
        
        //个人相册
        
        //判断是不是第一个cell被点击了
        if (indexPath.row == 0) {
            
            //初始化cell
            cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];
            
            //cell的类型
            cell.type = CelllTypeAdd;
        }else{

        }
    }else{
        
        //系统相册
        
        //初始化cell
        cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];
        
        //传递数据
        cell.model = self.pictureModelArray[indexPath.row];
        
        //cell的类型
        cell.type = CellTypeSystem;
    }
    
    return cell;
}

//item被点击了
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
    
    //判断类型
    if (self.type == ViewTypePerson) {
        
        //个人相册
        
        //判断是不是第一个被点击了
        if (indexPath.row == 0) {
     
        }else{
            
            //第一个之外的被点击了
            
            //判断是不是编辑状态
            if (self.isEditing) {
                
                //编辑状态
         
            }else{
                
                //进入浏览界面
      
    }else{
        
        //系统相册
        
        //获取indexPath.row对应的model
        XLPictureModel *model = self.pictureModelArray[indexPath.row];
        //更改isSelected的状态
        model.isSelected = !model.isSelected;
        
        //获取当前的cell
        XLPictureCell *cell = (XLPictureCell*)[collectionView cellForItemAtIndexPath:indexPath];
        //将状态传递给cell
        [cell changeStatus:model.isSelected];
        
        //判断资源有没有被选中
        if (model.isSelected == YES) {
            
            //加入临时资源数组中
            [[XLSystemAlbumManager sharedSystemAlbum].selectedArray addObject:model];
        }else{
            
            //从临时资源数组中移除
            [[XLSystemAlbumManager sharedSystemAlbum].selectedArray removeObject:model];
        }
    }
}

@end

你可能感兴趣的:(个人相册开发(10))