iOS开发 自定义相册键盘

现在很多app都有用到相册选择等功能,网上也已经有了很多封装好了的第三方库,但是最近项目中,设计师突发奇想,想要节省用户选择成本,让我们实现相册键盘,不用跳转新的页面可以直接选择照片或者视频,类似于图中的样式:

图1.0

然后第一个想法,网上找轮子,然后找了一圈,并没有发现适用的,只好自己实现了。

我用的方法是利用UICollectionView实现,接下来贴上代码。

1.首先做好准备工作,在pod文件中导入下列第三方库:

  pod  'YBImageBrowser',' ~> 2.1.5'        

  pod  'SDWebImage',' ~> 4.4.6'

  pod  'Toast'

  pod  'Masonry',' ~> 1.1.0'

  pod  'SJVideoPlayer'

这些大都是常用的第三方库,从上到下的功能分别是:图片查看、图片加载、Toast提示、页面布局、视频播放。

2.然后在info.plist文件中添加相册权限提示:

图2

3.开始写代码,导入相应头文件和设置好相应的协议还有数据

#import "ViewController.h"

#import <SDWebImage/UIImageView+WebCache.h>

#import "YBImageBrowser.h"

#import <Photos/Photos.h>

#import "Masonry.h"

#import "UIView+Toast.h"

#import "HobbiesCollectionViewCell.h"

#import "TZImagePickerController.h"

#import "YJVideoController.h"

#import "VideoPlayViewController.h"

@interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout,UINavigationControllerDelegate,UIImagePickerControllerDelegate,YBImageBrowserDataSource,UIGestureRecognizerDelegate,TZImagePickerControllerDelegate>

{

    UICollectionView*myCollectionView;            //相册瀑布流

    NSMutableArray*imageArray;                    //图片数组

    NSMutableArray*selectArray;                    //图片选择数组

    NSMutableArray*phArray;                        //媒体数据数组

    NSIntegernums;                                //最大可选择的照片数量

    NSInteger  IorV;                                //视频还是照片 -1:未选择  0:照片  1:视频

    UIView*bottomV;                                //相册所在的父视图

    UIView*toolView;                              //相册上方的工具视图(可自定义)

    UISwipeGestureRecognizer* recognizerUp;        //上滑手势

    UISwipeGestureRecognizer* recognizerDown;      //下拉手势

    BOOLisTop;                                    //是否滑动到顶部

    BOOLUPorDown;                                  //是否是在全屏状态

    NSIntegerpage;                                //页码

    BOOLready;                                    //是否准备好再次刷新

}

@property(nonatomic,strong) UIImagePickerController *imagePicker;

@end

4.开始进入时候检查权限

-(void)checkPermissions

{

    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {

        if (status == PHAuthorizationStatusAuthorized) {

            dispatch_main_async_safe(^{

                [selfloadImageArray];

            });

        }else{

            //未获取相册权限

            [self showAlrtToSetting];

        }

    }];

}

/**

 检测到未开启相册权限之后的提醒

 */

-(void) showAlrtToSetting

{

    UIAlertController* alert = [UIAlertControlleralertControllerWithTitle:@"开启相册权限"message:@"打开相册权限,上传您喜欢的图片"preferredStyle:UIAlertControllerStyleAlert];

    UIAlertAction* cancelAction = [UIAlertActionactionWithTitle:@"再看看"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction*_Nonnullaction) {


    }];

    UIAlertAction * setAction = [UIAlertAction actionWithTitle:@"打开" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)

                                 {

                                     NSURL* url = [NSURLURLWithString:UIApplicationOpenSettingsURLString];

                                     dispatch_async(dispatch_get_main_queue(), ^{

                                         if([[UIApplicationsharedApplication]canOpenURL:url])

                                         {

                                             [[UIApplicationsharedApplication]openURL:urloptions:@{}completionHandler:^(BOOLsuccess) {

                                                 dispatch_main_async_safe(^{

                                                     [selfloadImageArray];

                                                 });

                                             }];

                                         }

                                     });

                                 }];

    [alertaddAction:cancelAction];

    [alertaddAction:setAction];

    [self presentViewController:alert animated:YES completion:nil];

}

5.然后初始化视图

-(void)initUI

{

    self.view.backgroundColor = [UIColor lightGrayColor];

    nums=0;

    IorV= -1;

    ready=YES;

    isTop=NO;

    page=0;


    toolView = [[UIView alloc] initWithFrame:CGRectMake(0, HEIGHT-221-kSafeAreaBottomHeight-44, WIDTH, 44)];

    toolView.backgroundColor = [UIColor whiteColor];

    toolView.tag=88;

    [self.viewaddSubview:toolView];


    bottomV= [[UIViewalloc]init];

    [self.viewaddSubview:bottomV];

    [bottomV mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.right.equalTo(self.view);

        make.top.equalTo(toolView.mas_bottom);

        make.height.mas_equalTo(HEIGHT+221+kSafeAreaBottomHeight);

    }];


    //创建一个layout布局类

    UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc]init];

    //设置布局方向为垂直流布局

    layout.scrollDirection = UICollectionViewScrollDirectionVertical;

    //设置每个item的大小为100*100

    layout.itemSize=CGSizeMake(WIDTH/4-1,WIDTH/4-1);

    //创建collectionView 通过一个布局策略layout来创建


    myCollectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, 221+kSafeAreaBottomHeight) collectionViewLayout:layout];

    myCollectionView.delegate = self;

    myCollectionView.dataSource = self;

    myCollectionView.scrollEnabled = YES;

    myCollectionView.bounces = NO;

    myCollectionView.backgroundColor = [UIColor blackColor];

    //注册Cell

    [myCollectionView registerNib:[UINib nibWithNibName:@"HobbiesCollectionViewCell" bundle: [NSBundle mainBundle]] forCellWithReuseIdentifier:@"HobbiesCollectionViewCell"];

    [bottomV addSubview:myCollectionView];

    recognizerUp= [[UISwipeGestureRecognizeralloc]initWithTarget:selfaction:@selector(handleSwipeFrom:)];

    recognizerUp.direction = UISwipeGestureRecognizerDirectionUp;

    recognizerUp.delegate = self;

    [self.view addGestureRecognizer:recognizerUp];


    recognizerDown= [[UISwipeGestureRecognizeralloc]initWithTarget:selfaction:@selector(handleSwipeFrom:)];

    recognizerDown.direction = UISwipeGestureRecognizerDirectionDown;

    recognizerDown.delegate = self;

    [self.view addGestureRecognizer:recognizerDown];

}

6.加载本地照片和视频数据

-(void)loadImageArray

{

    [self.view makeToastActivity:CENTER];

    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        // 处理耗时操作的代码块

        phArray= [NSMutableArrayarray];

        imageArray= [NSMutableArrayarray];

        PHFetchOptions *options = [[PHFetchOptions alloc] init];

        options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];

        PHFetchResult*assetsFetchResults = [PHAssetfetchAssetsWithOptions:options];

        for(PHAsset*assetinassetsFetchResults)

        {

            //判断本地媒体数据是照片类型和视频类型,就加入到phArray数组中

            if (asset.mediaType == PHAssetMediaTypeImage || asset.mediaType == PHAssetMediaTypeVideo)

            {

                [phArrayaddObject:asset];

            }

        }

        phArray=(NSMutableArray *)[[phArray reverseObjectEnumerator] allObjects];  //数组倒序排列

        //加载前两百条数据(防止加载耗时过长)

        NSIntegercounts =phArray.count;

        if(counts>200)

        {

            counts =200;

        }

        for(inti=0;i

        {

            PHAsset*asset = [phArrayobjectAtIndex:i];

            PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];

            /** resizeMode:对请求的图像怎样缩放。有三种选择:None,默认加载方式;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。 deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。

             这个属性只有在 synchronous 为 true 时有效。

             */

            option.resizeMode = PHImageRequestOptionsResizeModeFast;//控制照片尺寸

            option.deliveryMode=1;//控制照片质量

            option.synchronous=YES;

            option.networkAccessAllowed=YES;

            //param:targetSize 即你想要的图片尺寸,若想要原尺寸则可输入PHImageManagerMaximumSize

            [[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(WIDTH/4, HEIGHT/4) contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable image, NSDictionary * _Nullable info) {

                NSString*types =@"0";  //0:照片 1:视频

                if(asset.mediaType==PHAssetMediaTypeImage)

                {

                    types =@"0";

                }

                else

                {

                    types =@"1";

                }

                NSDictionary*dic =@{@"image":image,@"type":types,@"times":@"0"};

                [imageArrayaddObject:dic];

            }];

        }


        //初始化是否选择的数组

        selectArray= [NSMutableArrayarray];

        for(inti=0;i

        {

            [selectArrayaddObject:@"0"];

        }

        //通知主线程刷新

        dispatch_async(dispatch_get_main_queue(), ^{

            //回调或者说是通知主线程刷新

            [myCollectionViewreloadData];

            [self.viewhideToastActivity];

        });

    });

}

7.上滑和下拉操作手势实现方法

- (void)handleSwipeFrom:(UISwipeGestureRecognizer*)recognizer

{

    if(recognizer.direction ==UISwipeGestureRecognizerDirectionUp) //上拉

    {

        if(!UPorDown)

        {

            CGFloatyy =toolView.frame.origin.y;

            if(yy>100)

            {

                [UIView animateWithDuration:0.5 animations:^{

                    toolView.transform=CGAffineTransformMakeTranslation(0, -yy+kStatusBarHeight);

                    bottomV.transform=CGAffineTransformMakeTranslation(0, -yy+kStatusBarHeight);

                    myCollectionView.frame=CGRectMake(0,0,WIDTH,HEIGHT-44-kStatusBarHeight);

                }completion:^(BOOLfinished){

                }];

            }


            UPorDown=YES;

        }

    }

    else if(recognizer.direction ==UISwipeGestureRecognizerDirectionDown)  //下滑

    {

        if(UPorDown)

        {

            if(isTop)

            {

                [UIView animateWithDuration:0.5 animations:^{

                    toolView.transform = CGAffineTransformMakeTranslation(0, 0);

                    bottomV.transform = CGAffineTransformMakeTranslation(0, 0);

                }completion:^(BOOLfinished){

                    myCollectionView.frame=CGRectMake(0,0,WIDTH,221+kSafeAreaBottomHeight);

                }];

                UPorDown=NO;

            }

        }

    }

}

8.下拉加载下一页(200条)的数据

-(void)footerClick

{

    if(phArray.count<200)

    {

        return;

    }

    ready=NO;

    NSIntegercounts =phArray.count;

    NSIntegernowCounts =200+page*200;

    if(nowCounts < counts)

    {

        if(nowCounts < counts -200)

        {

            counts = nowCounts +200;

        }

    }


    dispatch_async(dispatch_get_global_queue(0, 0), ^{

        // 处理耗时操作的代码块

        for(NSIntegeri=nowCounts;i

        {

            PHAsset*asset = [phArrayobjectAtIndex:i];

            PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];

            /** resizeMode:对请求的图像怎样缩放。有三种选择:None,默认加载方式;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。 deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。

             这个属性只有在 synchronous 为 true 时有效。

             */

            option.resizeMode = PHImageRequestOptionsResizeModeFast;//控制照片尺寸

            option.deliveryMode=1;//控制照片质量

            option.synchronous=YES;

            option.networkAccessAllowed=YES;

            //param:targetSize 即你想要的图片尺寸,若想要原尺寸则可输入PHImageManagerMaximumSize

            [[PHCachingImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(WIDTH/4, HEIGHT/4) contentMode:PHImageContentModeAspectFit options:option resultHandler:^(UIImage * _Nullable image, NSDictionary * _Nullable info) {

                NSString*types =@"0";  //0:照片 1:视频

                if(asset.mediaType==PHAssetMediaTypeImage)

                {

                    types =@"0";

                }

                else

                {

                    types =@"1";

                }

                NSDictionary*dic =@{@"image":image,@"type":types,@"times":@"0"};

                [imageArrayaddObject:dic];

                [selectArrayaddObject:@"0"];

            }];

        }


        //通知主线程刷新

        dispatch_async(dispatch_get_main_queue(), ^{

            //回调或者说是通知主线程刷新

            [myCollectionViewreloadData];

            [self.viewhideToastActivity];

            page++;

            ready=YES;

        });

    });

}

9.手势协议的实现(防止UICollectionView的滚动事件和手势冲突)

- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer

{

    return YES;

}

- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldReceiveTouch:(UITouch*)touch

{

    if([NSStringFromClass([touch.view class]) isEqualToString:@"UIView"])

    {

        UIView*vies = touch.view;

        if(vies.tag==88)

        {

            isTop=YES;

        }

    }

    if([NSStringFromClass([touch.view class]) isEqual:@"UICollectionView"])

    {

        returnNO;

    }

    else

    {

        returnYES;

    }

}

10.滚动过程中的监听

- (void)scrollViewDidScroll:(UIScrollView*)scrollView

{

    CGPointlocalPoint = scrollView.contentOffset;

    if(localPoint.y<=0)

    {

        isTop=YES;

    }

    else

    {

        isTop=NO;

        if(localPoint.y>(page+1)*3800)  //还未到达最底部就开始加载下200条,预防卡顿

        {

            if(ready)

            {

                [selffooterClick];

            }

        }

    }

}

11.CollectionView协议方法实现

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView*)collectionView

{

    return1;

}

/**

 设置CollectionView每组所包含的个数

 */

- (NSInteger)collectionView:(UICollectionView*)collectionView numberOfItemsInSection:(NSInteger)section

{

    return imageArray.count;

}

/**

 设置CollectionCell的内容

 */

- (UICollectionViewCell*)collectionView:(UICollectionView*)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath

{

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

    cell.bgImageView.image = [imageArray[indexPath.row] objectForKey:@"image"];

    if([[imageArray[indexPath.row] objectForKey:@"type"] isEqualToString:@"0"])  //照片类型,隐藏视频相关控件

    {

        cell.playImageView.hidden =YES;

        cell.playMengView.hidden =YES;

        cell.playTimeLabel.hidden =YES;

    }

    else  //视频类型

    {

        cell.playImageView.hidden =NO;

        cell.playMengView.hidden =NO;

        cell.playTimeLabel.hidden =NO;

        if([[imageArray[indexPath.row] objectForKey:@"times"] isEqualToString:@"0"])

        {  //异步获取视频时长

            dispatch_async(dispatch_get_global_queue(0,0), ^{

                // 处理耗时操作的代码块...

                PHAsset *asset = [phArray objectAtIndex:indexPath.row];

                __blockintseconds;

                [[TZImageManager manager] getVideoWithAsset:asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {

                    AVAsset *avasset = playerItem.asset;

                    AVURLAsset *urlAsset = (AVURLAsset *)avasset;

                    CMTime time = [urlAsset duration];

                    seconds = (int)time.value/time.timescale;

                    NSDictionary *dic =@{@"image":[imageArray[indexPath.row] objectForKey:@"image"],@"type":[imageArray[indexPath.row] objectForKey:@"type"],@"times":[NSString stringWithFormat:@"%d",seconds]};

                    [imageArray replaceObjectAtIndex:indexPath.row withObject:dic];

                }];

                //通知主线程刷新

                dispatch_async(dispatch_get_main_queue(), ^{

                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0f* NSEC_PER_SEC)), dispatch_get_main_queue(), ^{

                        [myCollectionView reloadData];

                    });

                });

            });

        }

        else

        {

            cell.playTimeLabel.text = [selftimeEdit:[NSString stringWithFormat:@"%@",[imageArray[indexPath.row] objectForKey:@"times"]]];

        }

    }


    //处理选择后的显示

    if([selectArray[indexPath.row] isEqualToString:@"0"])

    {

        cell.selectImageView.backgroundColor = [UIColor clearColor];

        cell.cellNumLabel.text =@"";

        cell.selectImageView.image = [UIImage imageNamed:@"noSelect"];

    }

    else

    {

        cell.selectImageView.backgroundColor = [UIColor colorWithRed:(255)/255.0green:(175)/255.0blue:(33)/255.0alpha:1.0];

        cell.selectImageView.image =nil;

        cell.cellNumLabel.text = selectArray[indexPath.row];

    }

    cell.selectImageView.hidden =NO;

    cell.selectBtn.tag = indexPath.row;

    [cell.selectBtn addTarget:selfaction:@selector(selectBtnClicked:) forControlEvents:UIControlEventTouchUpInside];


    returncell;

}

/**

 定义每个UICollectionView的大小

 */

- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath*)indexPath

{

    return  CGSizeMake(WIDTH/4-1,WIDTH/4-1);

}

/**

 定义整个CollectionViewCell与整个View的间距

 */

- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section

{

    return UIEdgeInsetsMake(1, 1, 1, 1);//(上、左、下、右)

}

/**

 定义每个UICollectionView的横向间距

 */

- (CGFloat)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section

{

    return0;

}

/**

 定义每个UICollectionView的纵向间距

 */

- (CGFloat)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section

{

    return0;

}

/**

 点击CollectionView触发事件

 */

-(void)collectionView:(UICollectionView*)collectionView didSelectItemAtIndexPath:(NSIndexPath*)indexPath

{

    if([[imageArray[indexPath.row]objectForKey:@"type"]isEqualToString:@"0"])//照片

    {

        [selflookImage:indexPath.row];

    }

    else

    {

        [selflookVideo:indexPath.row];

    }

}

/**

 设置CollectionViewCell是否可以被点击

 */

- (BOOL)collectionView:(UICollectionView*)collectionView shouldSelectItemAtIndexPath:(NSIndexPath*)indexPath

{

    return YES;

}

12.时间格式处理

-(NSString*)timeEdit:(NSString*)times

{

    inttimeNum = [timesintValue];

    if(timeNum<10)

    {

        return[NSStringstringWithFormat:@"00:0%d",timeNum];

    }

    elseif(timeNum<60)

    {

        return[NSStringstringWithFormat:@"00:%d",timeNum];

    }

    else

    {

        inta = timeNum%60;

        intb = timeNum/60;

        if(a<10)

        {

            if(b<10)

            {

                return[NSStringstringWithFormat:@"0%d:0%d",b,a];

            }

            else

            {

                return[NSStringstringWithFormat:@"%d:0%d",b,a];

            }

        }

        else

        {

            if(b<10)

            {

                return[NSStringstringWithFormat:@"0%d:%d",b,a];

            }

            else

            {

                return[NSStringstringWithFormat:@"%d:%d",b,a];

            }

        }

    }

}

13.查看图片

-(void)lookImage:(NSInteger)currentIndex

{

    YBImageBrowser *browser = [YBImageBrowser new];

    browser.dataSource=self;

    browser.currentIndex= currentIndex;

    //展示

    [browsershow];

}

14.查看视频(单独写了一个查看视频文件,详情请看下方git链接)

-(void)lookVideo:(NSInteger)currentIndex

{

    PHAsset*phAsset =phArray[currentIndex];

    if(phAsset.mediaType==PHAssetMediaTypeVideo) {

        PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];

        options.version = PHImageRequestOptionsVersionCurrent;

        options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;

        PHImageManager *manager = [PHImageManager defaultManager];

        [managerrequestAVAssetForVideo:phAssetoptions:optionsresultHandler:^(AVAsset*_Nullableasset,AVAudioMix*_NullableaudioMix,NSDictionary*_Nullableinfo) {

            AVURLAsset*urlAsset = (AVURLAsset*)asset;

            NSURL*url = urlAsset.URL;

            NSString*urls = [NSStringstringWithFormat:@"%@",url];

            VideoPlayViewController *playVC = [[VideoPlayViewController alloc] init];

            playVC.url= urls;

            [self presentViewController:playVC  animated:YES completion:nil];

        }];

    }

}

15.选择视频或照片实现

-(void)selectBtnClicked:(UIButton*)sender

{

    if(nums==0)

    {

        IorV= -1;

    }

    if([[imageArray[sender.tag] objectForKey:@"type"] isEqualToString:@"0"]) //照片

    {

        if(IorV==1)

        {

            [self.viewmakeToast:@"视频和照片只能上传一种!"duration:2position:CENTER];

            return;

        }

        IorV=0;

        if([selectArray[sender.tag]isEqualToString:@"0"])

        {

            if(nums==9)

            {

                [self.viewmakeToast:@"最多只能选择9张照片!"duration:2position:CENTER];

                return;

            }

            nums++;

            [selectArray replaceObjectAtIndex:sender.tag withObject:[NSString stringWithFormat:@"%ld",(long)nums]];

            [myCollectionViewreloadData];

        }

        else

        {

            if([selectArray[sender.tag]integerValue] ==9)//是最后一个只要刷新最后一条的数据

            {

                [selectArrayreplaceObjectAtIndex:sender.tagwithObject:@"0"];

                [myCollectionViewreloadData];

            }

            else

            {


                for(inti=0;i

                {

                    NSIntegerindexs = [selectArray[i]integerValue];

                    if(indexs>[selectArray[sender.tag]integerValue])

                    {

                        [selectArray replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%ld",(long)indexs]];

                    }

                }

                [selectArrayreplaceObjectAtIndex:sender.tagwithObject:@"0"];

                [myCollectionViewreloadData];

            }

            nums--;

        }

    }

    else

    {

        if(IorV==0)

        {

            [self.viewmakeToast:@"视频和照片只能上传一种!"duration:2position:CENTER];

            return;

        }

        IorV=1;

        if([selectArray[sender.tag]isEqualToString:@"0"])

        {

            if(nums==1)

            {

                [self.viewmakeToast:@"最多只能选择1个视频!"duration:2position:CENTER];

                return;

            }

            nums++;

            [selectArray replaceObjectAtIndex:sender.tag withObject:[NSString stringWithFormat:@"%ld",(long)nums]];

            [myCollectionViewreloadData];

        }

        else

        {

            [selectArray replaceObjectAtIndex:sender.tag withObject:@"0"];

            [myCollectionViewreloadData];

            nums-- ;

        }

    }

}

16.YBImageBrowserDataSource 代理实现赋值数据(图片查看)

- (NSUInteger)yb_numberOfCellForImageBrowserView:(YBImageBrowserView*)imageBrowserView {

    returnphArray.count;

}

- (id)yb_imageBrowserView:(YBImageBrowserView*)imageBrowserView dataForCellAtIndex:(NSUInteger)index {

    YBImageBrowseCellData *data = [YBImageBrowseCellData new];

    data.phAsset=phArray[index];

    returndata;

}


备注:目前根据项目,最多只能选择9张图片,并且图片和视频只能选择一种,所以做了限制。选择完成后,循环遍历selectArray既可获得所选的文件数据,代码大致如下:

{

    imageUrlArray = [NSMutableArray array];

    NSMutableArray *postImgArray = [NSMutableArray array];

    for(inti=0;i

    {

        if(![selectArray[i] isEqualToString:@"0"])

        {

            PHAsset *asset = phArray[i];

            if(IorV==1)  //视频

            {

                //视频只能选择一个,直接这里转视频,然后上传

                if(asset.mediaType == PHAssetMediaTypeVideo)

                {

                    [[TZImageManager manager] getVideoWithAsset:asset completion:^(AVPlayerItem *playerItem, NSDictionary *info) {

                        AVAsset *avasset = playerItem.asset;

                        AVURLAsset *urlAsset = (AVURLAsset *)avasset;

                        NSURL *urls = urlAsset.URL;

                        CMTime time = [urlAsset duration];

                        intseconds = ceil(time.value/time.timescale);

                        NSLog(@"视频时长:%d",seconds);


                        NSData *data = [NSData dataWithContentsOfURL:urls];

                        NSInteger videoSize = data.length/1024;

                        floatsizes = (float)videoSize/1024;

                        NSLog(@"视频大小:%.2f M",sizes);

                        /*

                         创建AVAssetExportSession对象

                         压缩的质量

                         AVAssetExportPresetLowQuality 最low的画质最好不要选择实在是看不清楚

                         AVAssetExportPresetMediumQuality 使用到压缩的话都说用这个

                         AVAssetExportPresetHighestQuality 最清晰的画质

                         */

                        AVAssetExportSession * session = [[AVAssetExportSession alloc] initWithAsset:avasset presetName:AVAssetExportPreset960x540];

                        //优化网络

                        session.shouldOptimizeForNetworkUse =YES;

                        //转换后的格式

                        //拼接输出文件路径 为了防止同名 可以根据日期拼接名字 或者对名字进行MD5加密

                        NSString* path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent:@"hello.mp4"];

                        //判断文件是否存在,如果已经存在删除

                        [[NSFileManager defaultManager]removeItemAtPath:path error:nil];

                        //设置输出路径

                        session.outputURL = [NSURL fileURLWithPath:path];

                        //设置输出类型 这里可以更改输出的类型 具体可以看文档描述

                        session.outputFileType = AVFileTypeMPEG4;

                        session.videoComposition = [selfgetVideoComposition:urlAsset];

                        [session exportAsynchronouslyWithCompletionHandler:^{

                            //压缩完成

                            if(session.status==AVAssetExportSessionStatusCompleted) {

                                //在主线程中刷新UI界面,弹出控制器通知用户压缩完成

                                dispatch_async(dispatch_get_main_queue(), ^{

                                    NSLog(@"导出完成");

                                    NSURL *beforeurl = session.outputURL;

                                    NSData *datass = [NSData dataWithContentsOfURL:beforeurl];

                                    NSInteger videoSizess = datass.length/1024;

                                    floatsizess = (float)videoSizess/1024;

                                    NSLog(@"压缩完毕,压缩后大小 %.2f MB",sizess);

                                    //去上传视频,地址为beforeurl

                                });

                            }

                        }];

                    }];

                    break;

                }

            }

            else

            {

                //照片可以传多张,所以循环添加进postImgArray

                PHImageManager *manager = [PHImageManager defaultManager];

                PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];

                /** resizeMode:对请求的图像怎样缩放。有三种选择:None,默认加载方式;Fast,尽快地提供接近或稍微大于要求的尺寸;Exact,精准提供要求的尺寸。 deliveryMode:图像质量。有三种值:Opportunistic,在速度与质量中均衡;HighQualityFormat,不管花费多长时间,提供高质量图像;FastFormat,以最快速度提供好的质量。

                 这个属性只有在 synchronous 为 true 时有效。

                 */

                option.resizeMode = PHImageRequestOptionsResizeModeFast;//控制照片尺寸

                option.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat;//控制照片质量

                option.synchronous =YES;

                option.networkAccessAllowed =YES;

                [manager requestImageForAsset:phArray[i] targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:option resultHandler:^(UIImage *resultImage, NSDictionary *info)

                 {

                     [postImgArray addObject:resultImage];

                     if(postImgArray.count == nums)

                     {

                         //当postImgArray的数量和开始记录的选中数量相等的时候,开始上传操作

                     }

                 }];

            }

        }

    }

}

大致思路是如此,第一次写简书,比较乱,大家勿怪,下方贴上github链接,可以下载下来看demo参考,顺便给个star,感谢🙏。祝大家生活愉快,永不脱发。

GitHub链接:https://github.com/bingegegege/photosPicker.git

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

推荐阅读更多精彩内容