iOS 使用PHPickerViewController选择图片和视频

iOS 14开始推出了PHPicker,更加快了UIImagePickerController退出历史舞台的步伐,取而代之的是PHPickerViewController,但PHPicker现在只能在iOS上使用,macOS、tvOS及watchOS下不可用。PHPicker还是依赖PHPhotoLibrary,只是PHPickerViewController在处理代理结果回调上有所变化,返回的是新的类PHPickerResult,而不再是通过NSDictionary信息获取PHAsset或UIImage对象。

另外PHPickerViewController只申明了一个代理事件,也就是说不管是选择视频、图片,还是取消操作都是在同一个代理事件中进行处理,而UIImagePickerController分别提供了图片、视频、取消三个代理事件,不同的操作需要实现不同的代理事件。

使用PHPickerViewController选择图片需要关键的两个类:PHPickerConfiguration和PHPickerFilter。PHPickerConfiguration用来对PHPickerViewController进行相关配置,包括模式、数量及过滤器(PHPickerFilter);PHPickerFilter用于设置所过滤的文件类型,包括图片、视频及现场图片(LivePhoto)。

初始化

//为了不影响14以下系统功能,需要做向下兼容

    if(@available(iOS14, *)) {

        //初始化过滤器(PHPickerFilter)

        PHPickerFilter *filter = [PHPickerFilter anyFilterMatchingSubfilters:@[PHPickerFilter.videosFilter]];//过滤器提供三种类型的过滤imagesFilter、videosFilter和livePhotosFilter

        //初始化PHPickerConfiguration对象(信息配置)

        PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];

        //设置过滤器,默认为nil,表示选择所有类型的文件

        config.filter= filter;

        //设置模式包括Automatic、Current和Compatible(分别代表最佳、当前、最兼容),默认为Automatic

        config.preferredAssetRepresentationMode = PHPickerConfigurationAssetRepresentationModeCurrent;

        //设置选择最大数量,默认为1,0表示系统最大数量值

        config.selectionLimit=1;

        //初始化图片选择控制器

        PHPickerViewController *pickerVC = [[PHPickerViewController alloc] initWithConfiguration:config];

        //设置选择控制器代理

        pickerVC.delegate=self;

        //展示

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

    }else{

        // Fallback on earlier versions

        // You can use UIImagePickerController to do something here.

    }

实现PHPickerViewControllerDelegate代理方法

实现代理方法

#pragma mark - PHPickerViewControllerDelegate

- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray *)results  API_AVAILABLE(ios(14)){

    [picker dismissViewControllerAnimated:YES completion:nil];

    if(!results || !results.count) {

        //点击了取消

    }else{

        //这里演示一张图片的

        //取出PHPickerResult对象,PHPickerResult类公开itemProvider和assetIdentifier属性,其中itemProvider用来获取资源文件的数据或对象,assetIdentifier文档里只做了属性说明就是文件的一个本地唯一ID,苹果官方操作指南也没有提到这个属性用法,只是对assetIdentifier做了一下简单的本地缓存和过滤操作(是否选择同一个文件)

        PHPickerResult *result = [resultsfirstObject];

        //定义NSItemProvider对象

        NSItemProvider *itemProvoider = result.itemProvider;

        //根据判断并加载文件

        if ([itemProvoider canLoadObjectOfClass:[PHLivePhoto class]]) {

            //或者[result.itemProvider canLoadObjectOfClass:[UIImage class]]

            [itemProvoider loadObjectOfClass:[PHLivePhoto class] completionHandler:^(__kindof id  _Nullable object, NSError * _Nullable error) {

                //返回的object属于PHLivePhoto对象,如果load的类是UIImage这里的object返回UIImage类

                //处理PHLivePhoto对象

                PHLivePhoto *lpObj = (PHLivePhoto*)object;

                NSURL *url = [lpObj valueForKey:@"imageURL"];//图片本地URL

                UIImage *image = [UIImage imageWithContentsOfFile:[url path]];//得到的图片UIImage对象

                //或者[NSData dataWithContentsOfFile:[url path]]转NSData数据

                dispatch_async(dispatch_get_main_queue(), ^{

                    self.resultImg.image = image;

                });

            }];

        }else{

            //图片

            if ([itemProvoider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {

                [itemProvoider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(__kindof id  _Nullable item, NSError * _Null_unspecified error) {

                    if([item isKindOfClass:[NSURL class]]) {

                        NSURL*url = (NSURL*)item;//图片本地URL

                        UIImage *image = [UIImage imageWithContentsOfFile:[url path]];//得到的图片UIImage对象

                        //或者[NSData dataWithContentsOfFile:[url path]]转NSData数据

                        dispatch_async(dispatch_get_main_queue(), ^{

                            self.resultImg.image = image;

                        });

                    }

                }];

            }

            //这里演示一个视频

            if ([itemProvoider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeVideo]) {

                [itemProvoider loadItemForTypeIdentifier:(NSString *)kUTTypeVideo options:nil completionHandler:^(__kindof id  _Nullable item, NSError * _Null_unspecified error) {

                    NSURL*url = (NSURL*)item;//视频本地URL

                    NSData *data = [NSData dataWithContentsOfURL:url];//视频数据

                    //获取视频截图

                    AVURLAsset *urlAsset = [AVURLAsset assetWithURL:url];

                    AVAssetImageGenerator *imgGen = [[AVAssetImageGenerator alloc] initWithAsset:urlAsset];

                    //设定缩略图的方向,如果不设定,获取到的缩略图可能是被旋转过的,而不是正向的。

                    imgGen.appliesPreferredTrackTransform=YES;

                    //取第一秒的截图

                    CMTimecT =CMTimeMake(1, urlAsset.duration.timescale);

                    CMTime aT;NSError *err;

                    CGImageRef cgImg = [imgGen copyCGImageAtTime:cT actualTime:&aT error:&err];

                    UIImage *resultImg = [UIImage imageWithCGImage:cgImg];

                    if(resultImg) {

                        dispatch_async(dispatch_get_main_queue(), ^{

                            self.resultImg.image = resultImg;//展示截图

                        });

                    }else{

                        NSLog(@"截图失败");

                    }

                    self.videoData= data;//缓存视频数据

                }];

            }

        }

    }

}

在处理PHPickerViewControllerDelegate代理事件中,上述代码中出现的“kUTTypeImage”以及“kUTTypeVideo”,可以使用另一种方式去代替。NSItemProvider提供了一个数组类型属性registeredTypeIdentifiers,数组里存放TypeIdentifier,从而可以从数组取值替换掉“kUTTypeImage”和“kUTTypeVideo”:[itemProvoider.registeredTypeIdentifiers firstObject]替换“kUTTypeImage”

registeredTypeIdentifiers数组

如果在编译时报错:Use of undeclared identifier 'kUTTypeVideo’或者’kUTTypeImage’,那是因为没有导入MobileCoreServices或者CoreServices框架

解决步骤如下:TARGETS->Build Phases->Link Binary With Libraries,添加MobileCoreServices.framework或者CoreServices.framework,在需要用到的地方引入头文件#import /#import 

链入框架
引入头文件

运行看效果

效果

结尾附上官方链接Selecting Photos and Videos in iOS

以上所述如有错误,欢迎指教

你可能感兴趣的:(iOS 使用PHPickerViewController选择图片和视频)