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”
如果在编译时报错:Use of undeclared identifier 'kUTTypeVideo’或者’kUTTypeImage’,那是因为没有导入MobileCoreServices或者CoreServices框架
解决步骤如下:TARGETS->Build Phases->Link Binary With Libraries,添加MobileCoreServices.framework或者CoreServices.framework,在需要用到的地方引入头文件#import
运行看效果
结尾附上官方链接Selecting Photos and Videos in iOS
以上所述如有错误,欢迎指教