从相册多选照片更新界面的collectionView

此次我用的是三方QBImagePickerController, CTAssetsPickerController也可以, 他们之间的区别暂时我觉得是多选照片时, 前者是对钩√, 后者是排序号1234.., 个人觉得对钩似乎比较好看点就用了前者

注意, 如果要避免进入过一次相册后再进入, 让相册忘记之前选过的图片, 则不能对imagePicker使用懒加载, 每次进入相册都应是new一个新的picker

从图库回来后, 市面上的app基本都是以collectionView呈现多选后的图片, 如果未满最大可选照片数, 最后一个item会覆盖一个加号图片, 以示可以继续添加新的图片

所以创建collectionView就不写了

首先使用cocoaPods导入

pod 'CTAssetsPickerController',  '~> 3.3.0'

或者

pod 'QBImagePickerController', '~> 3.4.0'

本次就只写后者

然后引入头文件

#import <QBImagePickerController/QBImagePickerController.h>

然后签协议, 第三个不用说, 后两个是为了可以使用拍照功能

@interface QBViewController ()<UICollectionViewDelegate, UICollectionViewDataSource, QBImagePickerControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>

属性

@property (nonatomic, strong) NACollectionView *collectionView;
@property (nonatomic, strong) NAFlowLayout *flowLayout;
@property (nonatomic, strong) NSMutableArray *mArrOfPics;//存储UIImage的数组
@property (nonatomic, strong) QBImagePickerController *imagePickerController;//多选的PickerController
@property (nonatomic, strong) UIImagePickerController *imagePicker;//拍照的PickerController
@property (nonatomic, assign) NSInteger numOfPicCanBeChoosed;//监听距离最大限制数量还有多少张可被选中

如果想自定义相册的navigationBar, 我暂时没什么好办法, 就是点进去QBImagePickerController, 修改init方法中的setUpAlbumsViewController方法, 添加以下三行

//以下这三行我写的
navigationController.navigationBar.barTintColor = [UIColor colorWithRed:0 green:148 / 255.f blue:1 alpha:1];
//按钮字体颜色
navigationController.navigationBar.tintColor = [UIColor whiteColor];
//title字体大小和颜色
[[UINavigationBar appearance] setTitleTextAttributes:@{
                                                NSForegroundColorAttributeName:[UIColor whiteColor],
                                                       NSFontAttributeName:[UIFont systemFontOfSize:16 * [UIScreen mainScreen].bounds.size.width / 375]
                                                       }];

一开始先把该初始化的初始化, 我设置最多可选6张照片

- (void)viewDidLoad{
    [super viewDidLoad];

    _numOfPicCanBeChoosed = 6;
    _mArrOfPics = [NSMutableArray array];
    [self createCollectionView];
}

推出相机的imagePicker还是可以懒加载的

- (UIImagePickerController *)imagePicker{
    if (!_imagePicker) {
        _imagePicker = [[UIImagePickerController alloc] init];
        _imagePicker.delegate = self;
    
        //模态推出照相机页面的样式
        _imagePicker.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
//        _imagePicker.allowsEditing = YES;
        self.imagePicker.sourceType =   UIImagePickerControllerSourceTypeCamera;
    }
    return _imagePicker;
}

#pragma mark - 注销
- (void)dealloc{

    self.imagePickerController.delegate = nil;
    self.imagePicker.delegate = nil;
}

以下是collectionView三个协议方法, cell上面就是imageView和左上角的删除button, 当没选任何图片或者六张照片全满时, 删除按钮隐藏

#pragma mark - item个数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

    if (_mArrOfPics.count == 0) {
        return 1;
    }else if(_mArrOfPics.count > 0 && _mArrOfPics.count < 6){
        return _mArrOfPics.count + 1;
    }
    else if(_mArrOfPics.count == 6){
        return 6;
    }
    else{
        return 0;
    }
}

#pragma mark - 取出cell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    NACollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NACollectionViewCell" forIndexPath:indexPath];

    NSLog(@"!!!%ld", _mArrOfPics.count);

    //添加了照片
    if (_mArrOfPics.count > 0) {
        cell.buttonOfDelete.hidden = NO;
        for (NSInteger i = 0; i < _mArrOfPics.count; i++) {
            UIImage *image = _mArrOfPics[i];
            if (indexPath.row == i) {
            
                cell.buttonOfDelete.tag = indexPath.row;
                cell.imageViewOfPic.image = image;
            }
            if (indexPath.row == _mArrOfPics.count) {
                cell.imageViewOfPic.image = [UIImage imageNamed:@"add"];
                cell.buttonOfDelete.hidden = YES;
            }
        }
    }

    //没有添加照片时
    else{
        cell.buttonOfDelete.hidden = YES;
        cell.imageViewOfPic.image = [UIImage imageNamed:@"add"];
    }

    cell.deletePics = ^(UIButton *button){
    
        if (indexPath.row == button.tag) {
            [_mArrOfPics removeObjectAtIndex:indexPath.row];
            _numOfPicCanBeChoosed = 6 - _mArrOfPics.count;
            [_collectionView reloadData];
        }
    };

    return cell;
}

#pragma mark - 点击item
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

    if(_mArrOfPics.count < 6){
    
        if (indexPath.row == _mArrOfPics.count) {
        
            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle: UIAlertControllerStyleActionSheet];
            UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
            UIAlertAction *takePicAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
                [self selectImageFromCamera];
            }];
            UIAlertAction *albumAction = [UIAlertAction actionWithTitle:@"从手机相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
                [self choosePicFromAlbum];
            }];
            [alertController addAction:cancelAction];
            [alertController addAction:takePicAction];
            [alertController addAction:albumAction];
            [self presentViewController:alertController animated:YES completion:nil];
        }
    }
}

选择去相册则对应以下方法

#pragma mark - 从相册选
- (void)choosePicFromAlbum{
    //这样就可以让navi顶部与app风格一致
    //    UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:self.imagePickerController];

    _imagePickerController = [[QBImagePickerController alloc] init];
    //默认是any
    _imagePickerController.mediaType = QBImagePickerMediaTypeImage;
    _imagePickerController.assetCollectionSubtypes = @[
                                                   @(PHAssetCollectionSubtypeSmartAlbumUserLibrary), // Camera Roll
                                                   @(PHAssetCollectionSubtypeAlbumMyPhotoStream), // My Photo Stream
                                                   @(PHAssetCollectionSubtypeSmartAlbumPanoramas), // Panoramas
                                                   @(PHAssetCollectionSubtypeSmartAlbumVideos), // Videos
                                                   @(PHAssetCollectionSubtypeSmartAlbumBursts) // Bursts
                                                   ];

    //        _imagePickerController.prompt = @"选择照片";
    _imagePickerController.showsNumberOfSelectedAssets = YES;
    _imagePickerController.delegate = self;
    _imagePickerController.allowsMultipleSelection = YES;
    _imagePickerController.maximumNumberOfSelection = 6;

    //默认相册显示的预选照片尺寸
    _imagePickerController.numberOfColumnsInPortrait = 4;
    _imagePickerController.numberOfColumnsInLandscape = 7;

    [self presentViewController:self.imagePickerController animated:YES completion:nil];
}

进入相册就连带着调用了一些协议方法, 我选了两个需要用到的时机, 选完后和将要选择某张图片时, 后者是为了阻止超出图片最大限制数量

进入选完图片这个协议方法, 网上很多前辈进行数组初始化, 不, 万一这位用户只想在前面选择基础上继续添加图片呢

#pragma mark - 选完照片
- (void)qb_imagePickerController:(QBImagePickerController *)imagePickerController didFinishPickingAssets:(NSArray *)assets   {

//    _mArrOfPics = [NSMutableArray array];

    // 基本配置
    CGFloat scale = [UIScreen mainScreen].scale;
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.resizeMode   = PHImageRequestOptionsResizeModeNone;
    options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;

    for (PHAsset *asset in assets) {
        CGSize size = CGSizeMake(asset.pixelWidth / scale, asset.pixelHeight / scale);
        // 获取图片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        
            [_mArrOfPics addObject:result];
            self.numOfPicCanBeChoosed = 6 - _mArrOfPics.count;
            [_collectionView reloadData];
        }];
    }

    // 关闭图片选择界面
    [self dismissViewControllerAnimated:YES completion:nil];
}

接下来是将要选择图片时

#pragma mark - 要选中某张图片之前
- (BOOL)qb_imagePickerController:(QBImagePickerController *)imagePickerController shouldSelectAsset:(PHAsset *)asset{

    if(self.imagePickerController.selectedAssets.count + 1 <= self.numOfPicCanBeChoosed){
        return YES;
    }else{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"一次最多上传6张图片" preferredStyle:UIAlertControllerStyleAlert];
        [imagePickerController presentViewController:alert animated:YES completion:nil];
//让alert自动消失
        [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(creatAlert:) userInfo:alert repeats:NO];
        return NO;
    }
}

#pragma mark - 让警告消失
- (void)creatAlert:(NSTimer *)timer{

    UIAlertController *alert = [timer userInfo];
    [alert dismissViewControllerAnimated:YES completion:nil];
    alert = nil;
}

至于推出相机那部分, 之前有写过, 再写一遍, 区别就是拍照后, 监听剩余可添加图片数的属性变量要更新

#pragma mark - 选择拍照
- (void)selectImageFromCamera{

    //判断相机是否可用
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    
        //判断是否开启相机权限
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        //权限未开启
        if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
        
            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"抱歉" message:@"您尚未开启相机权限" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"去开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                //info plist中URL type中添加一个URL Schemes添加一个prefs值
                if([[UIApplication sharedApplication] canOpenURL:url]){
                    //跳转到隐私
                    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Privacy&path=CAMERA"]];
                }
            }];
            UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"不了" style:UIAlertActionStyleDefault handler:nil];
            [alertController addAction:actionOK];
            [alertController addAction:actionCancel];
            [self presentViewController:alertController animated:YES completion:nil];
        }
        //权限已开启
        else{
            [self presentViewController:self.imagePicker animated:YES completion:^{}];
        }
    }
    //适用于没有相机的设备
    else{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"抱歉" message:@"相机不可用" preferredStyle:UIAlertControllerStyleAlert];
        [self presentViewController:alertController animated:YES completion:nil];
#pragma mark - 让alert自动消失
        [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(creatAlert:) userInfo:alertController repeats:NO];
    }

}

协议方法, 获取拍照后的图片, 顺便刷新collectionView和监听剩余可选图片的属性

#pragma mark - ImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{

    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    //这个本来是想用于拍照后编辑的, 发现并没有用
    //self.isFullScreen = NO;

    //用拍下来的照片赋值
    [_mArrOfPics addObject:image];
    [_collectionView reloadData];

    self.imagePickerController.maximumNumberOfSelection = 6 - _mArrOfPics.count;
    self.numOfPicCanBeChoosed = 6 - _mArrOfPics.count;

    //访问相册权限, ios9之后的api, 要引入<Photos/Photos.h>
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];

    //相册权限已开启
    if(status == PHAuthorizationStatusAuthorized){
        //存入本地相册
        UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}

    //未开启相册权限
    //PHAuthorizationStatusNotDetermined,
    //PHAuthorizationStatusRestricted
    //PHAuthorizationStatusDenied
    else{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"您尚未开启相册权限" message:@"无法存入所拍的照片" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"去开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            //info plist中URL type中添加一个URL Schemes添加一个prefs值
            if([[UIApplication sharedApplication] canOpenURL:url]){
                //跳转到隐私
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Privacy&path=PHOTOS"]];
            }
        }];
        UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"不了" style:UIAlertActionStyleDefault handler:nil];
        [alertController addAction:actionOK];
        [alertController addAction:actionCancel];
        [self presentViewController:alertController animated:YES completion:nil];
    }
    [picker dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - 存储到系统相册结果回调
- (void)image:(UIImage*)image didFinishSavingWithError:  (NSError*)error contextInfo:(void*)contextInfo{
    if (error){
        NSLog(@"%@", error);
    }
    else{
        NSLog(@"保存成功");
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,029评论 4 62
  • 多么卑微,卑微如一条土狗,活得不像人,活得不如狗。从来低声下气,从来悄无声息。没有人记得,没有人爱惜。结结...
    赵明婳阅读 286评论 0 0
  • 覃朝望 昨天是周未,在北海从事南流江玉石加工的老表电活里告诉我,因为上一次环江同乡聚会已过去两年了,...
    潮望阅读 814评论 4 8
  • 街道外,车水马龙好喧嚣,狗窝处,泡面人生异常孤独。 其实丹丹最不喜欢吃泡面,但是没办法,人生考验到了这一part,...
    铜碗豆儿阅读 166评论 0 1
  • 近大远小。花托的尖尖,用力画,扎手的感觉,有没有?
    sxtyyys阅读 217评论 0 0