前言
蘋果在iOS14繼續(xù)加強(qiáng)了對(duì)用戶隱私的保護(hù),有時(shí)需求只是想選擇一張相冊(cè)中的圖片堂鲜,但是需要對(duì)App開發(fā)整個(gè)照片庫(kù)的權(quán)限既琴,一些私密照片也可以被App讀取到,這樣很不合理泡嘴!因此iOS14中對(duì)相冊(cè)權(quán)限新增了“Limited Photo Library Access” 模式甫恩,這樣用戶可以控制App允許訪問的照片。下面簡(jiǎn)單介紹下如何適配iOS14相冊(cè)新增的功能酌予。
相冊(cè)相關(guān)庫(kù)
iOS8以后蘋果逐漸使用Photos代替AssetsLibrary,這里主要使用Photos實(shí)現(xiàn)訪問系統(tǒng)相冊(cè)磺箕。如果還在使用AssetsLibrary請(qǐng)盡快使用新的 API實(shí)現(xiàn)相冊(cè)相關(guān)功能。項(xiàng)目中需要引入Photos和PhotoUI庫(kù)抛虫。
權(quán)限彈窗變化
- Select Photo(選擇照片): 限制訪問松靡,點(diǎn)擊之后會(huì)彈出系統(tǒng)的圖片選擇界面選擇資源,APP 只能訪問用戶選擇的資源建椰。
- Allow Access to All Photos(允許訪問所有照片): 可以訪問所有的資源雕欺。
- Don't Allow(不允許): 不允許訪問資源
PHPhotoLibrary新增API
PHPhotoLibrary用于獲取查看相冊(cè)權(quán)限,處理相冊(cè)變化棉姐,注冊(cè)監(jiān)聽相冊(cè)變化屠列,監(jiān)聽用戶添加/刪除了哪些照片。
- 權(quán)限枚舉
PHAuthorizationStatusNotDetermined 用戶未作出選擇
PHAuthorizationStatusRestricted 此App無權(quán)限訪問照片數(shù)據(jù)
PHAuthorizationStatusDenied 用戶已明確拒絕此應(yīng)用程序訪問照片數(shù)據(jù)
PHAuthorizationStatusAuthorized 用戶已授權(quán)此應(yīng)用程序訪問照片數(shù)據(jù)
PHAuthorizationStatusLimited 用戶已授權(quán)此應(yīng)用程序進(jìn)行有限照片庫(kù)訪問(iOS14新增)
- 權(quán)限等級(jí)枚舉
PHAccessLevelAddOnly 僅允許添加
PHAccessLevelReadWrite 讀寫
注意:PHAuthorizationStatusLimited 權(quán)限只在 accessLevel 為 PHAccessLevelReadWrite 時(shí)生效
- 權(quán)限獲取
新權(quán)限獲壬【亍:增加了權(quán)限等級(jí)
+ (PHAuthorizationStatus)authorizationStatusForAccessLevel:(PHAccessLevel)accessLevel
+ (void)requestAuthorizationForAccessLevel:(PHAccessLevel)accessLevel handler:(void(^)(PHAuthorizationStatus status))handler
舊權(quán)限獲取:在iOS14中已經(jīng)廢棄笛洛,建議使用上面的新API
+ (PHAuthorizationStatus)authorizationStatus
+ (void)requestAuthorization:(void(^)(PHAuthorizationStatus status))handler
注意:如果仍使用舊的API未適配iOS14新特性,這時(shí)獲取相冊(cè)權(quán)限狀態(tài)乃坤,就算在Limited 模式下也會(huì)返回Authorized
- 新增PHPicker
iOS 14 中系統(tǒng)新增了一個(gè)圖片選擇器PHPicker(iOS14以上使用)苛让,官方建議使用 PHPicker 來替代原有的UIImagePickerController(iOS14以下使用)進(jìn)行圖片選擇 沟蔑。UIImagePickerController只能選中一張圖片已經(jīng)不符合需求了,將逐漸被廢棄替換狱杰。
怎樣使用PHPicker
1瘦材、使用PHPickerConfiguration配置PHPicker,鍵selectionLimit 設(shè)置為0表示多選仿畸,設(shè)置為大于1表示只可選中一張圖片食棕,默認(rèn)值為1;使用filter設(shè)置想要的相冊(cè)資源類型颁湖,包括imagesFilter宣蠕、videosFilter、livePhotosFilter甥捺,亦可以設(shè)置為數(shù)組@[videoFilter,livePhotosFilter]顯示多種類型.
2抢蚀、設(shè)置PHPickerViewControllerDelegate代理,接收選中照片后的回調(diào)镰禾;
3皿曲、在代理回調(diào)piscker:didFinishPicking: 中處理返回結(jié)果PHPickerResult;
PHPicker優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 支持多選,可以設(shè)置選擇一個(gè)資源吴侦,還是多個(gè)資源屋休;
- 支持按 image,video备韧,livePhotos 類型進(jìn)行選擇劫樟;
- 只是資源搜索,在頁(yè)面上有搜索框织堂;
- 獨(dú)立進(jìn)程叠艳,不會(huì)影響App性能,如何體現(xiàn)呢:在設(shè)置→照片→照片權(quán)限設(shè)置中選擇點(diǎn)擊”選中的照片“后也會(huì)彈出PHPicker易阳,并且可以為App添加允許訪問的照片附较;
- 內(nèi)置隱私:不需要直接訪問用戶相冊(cè);不會(huì)彈出訪問相冊(cè)提示潦俺;僅為用戶提供選擇的照片和視頻(App 無法獲取其他照片)拒课;
缺點(diǎn):
- 不支持選中圖片的編輯,例如選中后裁剪成正方形事示,需要自定義實(shí)現(xiàn)了早像;
plist設(shè)置
NSPhotoLibraryAddUsageDescription
用戶存入相冊(cè)時(shí)的提示信息。
NSPhotoLibraryUsageDescription
相冊(cè)訪問權(quán)限信息很魂,必須有此項(xiàng)扎酷,不然訪問相冊(cè)的時(shí)候 APP 會(huì) Crash。
PHPhotoLibraryPreventAutomaticLimited
如果未適配遏匆,App在每次冷啟動(dòng)時(shí)都會(huì)觸發(fā)詢問用戶是否需要修改照片權(quán)限法挨,添加可供App訪問的圖片。
隱藏系統(tǒng)彈出的選擇圖片Alert
在首次啟動(dòng)訪問相冊(cè)權(quán)限幅聘,并且選擇了Limited權(quán)限后凡纳,再次冷啟動(dòng)的時(shí)候會(huì)自動(dòng)彈出權(quán)限選擇Alert,要求用戶選擇圖片帝蒿。
在info.plist中加入PHPhotoLibraryPreventAutomaticLimited = YES關(guān)閉系統(tǒng)自動(dòng)彈窗荐糜。并且使用下面的API主動(dòng)調(diào)用控制彈出PHPickerViewController 進(jìn)行照片選擇。(在應(yīng)該使用的地方使用)
[[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self];
使用示例
- 查詢權(quán)限
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelReadWrite];
switch (status) {
case PHAuthorizationStatusLimited:
NSLog(@"limited");
break;
case PHAuthorizationStatusDenied:
NSLog(@"denied");
break;
case PHAuthorizationStatusAuthorized:
NSLog(@"authorized");
break;
default:
break;
}
- 請(qǐng)求權(quán)限
[PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(PHAuthorizationStatus status) {
switch (status) {
case PHAuthorizationStatusLimited:
{
//用戶選擇Limited模式葛超,限制App訪問有限的相冊(cè)資源
NSMutableArray<UIImage *> *images = [NSMutableArray array];
//獲取可訪問的圖片配置選項(xiàng)
PHFetchOptions *option = [[PHFetchOptions alloc] init];
//根據(jù)圖片的創(chuàng)建時(shí)間升序排序返回
option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
//獲取類型為image的資源
PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:option];
//遍歷出每個(gè)PHAsset資源對(duì)象
[result enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
PHAsset *asset = (PHAsset *)obj;
//將PHAsset解析為image的配置選項(xiàng)
PHImageRequestOptions *requestOptions = [[PHImageRequestOptions alloc] init];
//圖像縮放模式
requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;
//圖片質(zhì)量
requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
//PHImageManager解析圖片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"圖片 %@",result);
//在這里可以自定義一個(gè)顯示可訪問相冊(cè)資源的viewController.
[images addObject:result];
}];
}];
break;
}
case PHAuthorizationStatusDenied:
{
NSLog(@"denied");
}
break;
case PHAuthorizationStatusAuthorized:
{
//用戶選擇"允許訪問所有照片"暴氏,調(diào)用PHPickerViewController顯示圖片選擇器
dispatch_async(dispatch_get_main_queue(), ^{
PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] init];
//只獲取image類型資源
configuration.filter = [PHPickerFilter imagesFilter];
//可以多選
configuration.selectionLimit = 0;
PHPickerViewController *pickerVC = [[PHPickerViewController alloc] initWithConfiguration:configuration];
pickerVC.delegate = self;
pickerVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:pickerVC animated:YES completion:^{
}];
});
}
break;
default:
break;
}
}];
返回結(jié)果:選中了三張圖片允許App訪問
注意: 我們通過requestImageForAsset獲取到允許訪問的圖片PHAsset對(duì)象后,解析為UIImage后绣张,需要開發(fā)者自定義一個(gè)顯示可訪問相冊(cè)資源的viewController.
- 主動(dòng)彈出選擇照片PHPickerViewController
[[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self];
- 選中圖片后的回調(diào)
- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results
{
[picker dismissViewControllerAnimated:YES completion:nil];
if (!results || !results.count) {
return;
}
NSLog(@"didFinishPicking");
}
注意:無論我們點(diǎn)擊完成還是取消都會(huì)調(diào)用這個(gè)回調(diào)答渔,當(dāng)點(diǎn)擊取消時(shí)results返回為空