iOS 14開始推出了PHPicker返奉,更加快了UIImagePickerController退出歷史舞臺的步伐现横,取而代之的是PHPickerViewController怀各,但PHPicker現(xiàn)在只能在iOS上使用听系,macOS舍悯、tvOS及watchOS下不可用航棱。PHPicker還是依賴PHPhotoLibrary,只是PHPickerViewController在處理代理結(jié)果回調(diào)上有所變化萌衬,返回的是新的類PHPickerResult饮醇,而不再是通過NSDictionary信息獲取PHAsset或UIImage對象。
另外PHPickerViewController只申明了一個代理事件奄薇,也就是說不管是選擇視頻驳阎、圖片,還是取消操作都是在同一個代理事件中進行處理馁蒂,而UIImagePickerController分別提供了圖片呵晚、視頻、取消三個代理事件沫屡,不同的操作需要實現(xiàn)不同的代理事件饵隙。
使用PHPickerViewController選擇圖片需要關鍵的兩個類:PHPickerConfiguration和PHPickerFilter。PHPickerConfiguration用來對PHPickerViewController進行相關配置沮脖,包括模式金矛、數(shù)量及過濾器(PHPickerFilter);PHPickerFilter用于設置所過濾的文件類型勺届,包括圖片驶俊、視頻及現(xiàn)場圖片(LivePhoto)。
//為了不影響14以下系統(tǒng)功能免姿,需要做向下兼容
? ? 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;
? ? ? ? //設置選擇最大數(shù)量,默認為1喻犁,0表示系統(tǒng)最大數(shù)量值
? ? ? ? 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.
? ? }
實現(xiàn)PHPickerViewControllerDelegate代理方法
#pragma mark - PHPickerViewControllerDelegate
- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult*> *)results? API_AVAILABLE(ios(14)){
? ? [picker dismissViewControllerAnimated:YES completion:nil];
? ? if(!results || !results.count) {
? ? ? ? //點擊了取消
? ? }else{
? ? ? ? //這里演示一張圖片的
? ? ? ? //取出PHPickerResult對象,PHPickerResult類公開itemProvider和assetIdentifier屬性槽片,其中itemProvider用來獲取資源文件的數(shù)據(jù)或?qū)ο蠛位海琣ssetIdentifier文檔里只做了屬性說明就是文件的一個本地唯一ID,蘋果官方操作指南也沒有提到這個屬性用法筐乳,只是對assetIdentifier做了一下簡單的本地緩存和過濾操作(是否選擇同一個文件)
? ? ? ? PHPickerResult *result = [resultsfirstObject];
? ? ? ? //定義NSItemProvider對象
? ? ? ? NSItemProvider *itemProvoider = result.itemProvider;
? ? ? ? //根據(jù)判斷并加載文件
? ? ? ? if ([itemProvoider canLoadObjectOfClass:[PHLivePhoto class]]) {
? ? ? ? ? ? //或者[result.itemProvider canLoadObjectOfClass:[UIImage class]]
? ? ? ? ? ? [itemProvoider loadObjectOfClass:[PHLivePhoto class] completionHandler:^(__kindof id<NSItemProviderReading>? _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]]轉(zhuǎn)NSData數(shù)據(jù)
? ? ? ? ? ? ? ? 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<NSSecureCoding>? _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]]轉(zhuǎn)NSData數(shù)據(jù)
? ? ? ? ? ? ? ? ? ? ? ? dispatch_async(dispatch_get_main_queue(), ^{
? ? ? ? ? ? ? ? ? ? ? ? ? ? self.resultImg.image = image;
? ? ? ? ? ? ? ? ? ? ? ? });
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }];
? ? ? ? ? ? }
? ? ? ? ? ? //這里演示一個視頻
? ? ? ? ? ? if ([itemProvoider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeVideo]) {
? ? ? ? ? ? ? ? [itemProvoider loadItemForTypeIdentifier:(NSString *)kUTTypeVideo options:nil completionHandler:^(__kindof id<NSSecureCoding>? _Nullable item, NSError * _Null_unspecified error) {
? ? ? ? ? ? ? ? ? ? NSURL*url = (NSURL*)item;//視頻本地URL
? ? ? ? ? ? ? ? ? ? NSData *data = [NSData dataWithContentsOfURL:url];//視頻數(shù)據(jù)
? ? ? ? ? ? ? ? ? ? //獲取視頻截圖
? ? ? ? ? ? ? ? ? ? AVURLAsset *urlAsset = [AVURLAsset assetWithURL:url];
? ? ? ? ? ? ? ? ? ? AVAssetImageGenerator *imgGen = [[AVAssetImageGenerator alloc] initWithAsset:urlAsset];
? ? ? ? ? ? ? ? ? ? //設定縮略圖的方向,如果不設定蝙云,獲取到的縮略圖可能是被旋轉(zhuǎn)過的氓皱,而不是正向的。
? ? ? ? ? ? ? ? ? ? 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;//緩存視頻數(shù)據(jù)
? ? ? ? ? ? ? ? }];
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
在處理PHPickerViewControllerDelegate代理事件中勃刨,上述代碼中出現(xiàn)的“kUTTypeImage”以及“kUTTypeVideo”波材,可以使用另一種方式去代替。NSItemProvider提供了一個數(shù)組類型屬性registeredTypeIdentifiers身隐,數(shù)組里存放TypeIdentifier廷区,從而可以從數(shù)組取值替換掉“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?<MobileCoreServices/MobileCoreServices.h>/#import?<CoreServices/CoreServices.h>
運行看效果
結(jié)尾附上官方鏈接Selecting Photos and Videos in iOS
以上所述如有錯誤隙轻,歡迎指教??