iOS 14适配相册权限

     最近需要适配iOS 14的相册权限,在网上查了很多资料,大部分资料都只讲一部分缺另一部分,想把整个相册权限适配好还是有点麻烦,现在办把我整个适配过程记录下来,需要适配的兄弟可以参考一下

     在 iOS13 及以前,当用户首次访问应用程序时,会被要求开放大量权限,比如相册、定位、联系人,实际上该应用可能仅仅需要一个选择图片功能,却被要求开放整个照片库的权限,这确实是不合理的。对于相册,在 iOS14 中引入了 “LimitedPhotos Library” 的概念,用户可以授予应用访问其一部分的照片,对于应用来说,仅能读取到用户选择让应用来读取的照片,让我们看到了 Apple 对于用户隐私的尊重。这仅仅是一部分,在iOS14 中,可以看到诸多类似的保护用户隐私的措施,也需要我们升级适配。 

      iOS14 新增了“Limited Photo Library Access” 模式,在授权弹窗中增加了 Select Photo 选项。用户可以在 App 请求调用相册时选择部分照片让 App 读取。从 App 的视⻆来看,你的相册里就只有这几张照片,App 无法得知其它照片的存在。


   当一下次在进入时有会弹提示框,让你选择更多图片或者保留当前选择,这个提示框不太友好,可以在plist文件里面通过设置 Prevent limited photos access alert = YES隐藏提示


当选择添加更多图片是,可以通过    [[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self];到相册添加删除图片,然后监听图片变化做相应处理。

对于PHAuthorizationStatusLimited权限的适配,我采用的方案是,先绘制一个列表用于显示授权的图片,图片的资源也就是授权访问的,当要添加更多图片是通过 [[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self];跳转到相册,添加图片,添加完成后监听图片变化,更新列表,下面是我的代码:

 if (@available(iOS 14.0, *)) {

            PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatusForAccessLevel:PHAccessLevelReadWrite];

              switch(status) {

                  case PHAuthorizationStatusNotDetermined:

                      [self dispatchAuthorizationForAccessLevel];

                      break;

                  case PHAuthorizationStatusLimited:

                      NSLog(@"limited");

                      [selfe_enterGDPickerVC];

                      break;

                      // 用户拒绝当前应用访问相册

                  case PHAuthorizationStatusDenied:

                      NSLog(@"denied");

                      [self disptachPHAuthorizationStatusDenied];

                      break;

                      // 用户允许当前应用访问相册

                  case PHAuthorizationStatusAuthorized:

                      NSLog(@"authorized");

                      [self P_enterPHPickerViewController];

                      break;

                  default:

                      break;

            }

        }

/用户第一次访问

-(void)dispatchAuthorizationForAccessLevel{

    [PHPhotoLibrary requestAuthorizationForAccessLevel:PHAccessLevelReadWrite handler:^(PHAuthorizationStatus status) {

                switch(status) {

                    case PHAuthorizationStatusLimited:

                    {

                        dispatch_async(dispatch_get_main_queue(), ^{

                            [selfe_enterGDPickerVC];

                        });

                        break;

                    }

                    case PHAuthorizationStatusDenied:

                    {

                        NSLog(@"denied");

                    }

                        break;

                    case PHAuthorizationStatusAuthorized:

                    {


                    }

                        break;

                    default:

                        break;

                }

            }];


}

//进入授权访问的图片控制器

-(void)e_enterGDPickerVC{

    MJWeakSelf;

    GDPickerVC *picker = [GDPickerVC new];

    picker.currentImageContent= ^(UIImage*_NonnullimageContent) {

        NSLog(@"--选择图片--");

        if(!imageContent) {

            return;

        }

        [weakSelfanalysisImageWithContent:imageContent];

    };

    UINavigationController *nv = [[UINavigationController alloc] initWithRootViewController:picker];

    nv.modalPresentationStyle  =0;

    [_controller presentViewController:nv animated:YES completion:nil];

}


----------授权图片列表--------------

//

//

#import "GDPickerVC.h"

#import

#import "GDPickerCollectionViewCell.h"

#define SCREEN_WIDTH ([[UIScreen mainScreen] bounds].size.width)

// 屏幕高度,会根据横竖屏的变化而变化

#define SCREEN_HEIGHT ([[UIScreen mainScreen] bounds].size.height)

@interface GDPickerVC ()

@property (nonatomic, strong) UICollectionView *collectionView;

@property (nonatomic, strong) NSMutableArray *photoArray;

@end

@implementation GDPickerVC

- (void)viewDidLoad {

    [super viewDidLoad];

    self.view.backgroundColor = [UIColor whiteColor];


    self.title = @"显示允许访问的图片";

    //左边返回按钮

    UIButton *fanHuiButton = [UIButton buttonWithType:UIButtonTypeCustom];

    fanHuiButton.frame=CGRectMake(0,0,30,40);

    [fanHuiButtonsetTitle:@"取消"forState:0];

    [fanHuiButtonsetTitleColor:[UIColor systemBlueColor] forState:0];

    [fanHuiButtonaddTarget:self action:@selector(comebackFuncation) forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem *leftItem = [[UIBarButtonItem alloc] initWithCustomView:fanHuiButton];

    self.navigationItem.leftBarButtonItem = leftItem;


    UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];

    rightButton.frame=CGRectMake(0,0,30,40);

    [rightButtonsetTitle:@"添加"forState:0];

    [rightButtonsetTitleColor:[UIColor systemBlueColor] forState:0];

    [rightButtonaddTarget:self action:@selector(confirmButton:) forControlEvents:UIControlEventTouchUpInside];

    UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithCustomView:rightButton];

    self.navigationItem.rightBarButtonItem = rightItem;


    //获取图片

    [self getLibarayPhotoImage];

    self.photoArray = [NSMutableArray array];

    [self.view addSubview:self.collectionView];


}

#pragma mark - UICollectionViewDataSource

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

{

    return CGSizeMake(SCREEN_WIDTH/3-2,SCREEN_WIDTH/3);

}

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

    return self.photoArray.count;

}

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

    UIImage*image =self.photoArray[indexPath.row];

    GDPickerCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass(GDPickerCollectionViewCell.class) forIndexPath:indexPath];

    cell.imgView.image= image;

    returncell;

}

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


    UIImage*image =self.photoArray[indexPath.row];

    if (_currentImageContent&&image) {

        _currentImageContent(image);

        [self comebackFuncation];

    }

}

#pragma response

//返回

-(void)comebackFuncation{

    [self dismissViewControllerAnimated:YES completion:nil];

}

//点击确认回调数据

-(void)confirmButton:(UIButton *)btn{

    [[PHPhotoLibrary sharedPhotoLibrary] presentLimitedLibraryPickerFromViewController:self];

    [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];

}

- (void)photoLibraryDidChange:(PHChange *)changeInstance

{

    [self.photoArray removeAllObjects];

    [self getLibarayPhotoImage];

}

/*  遍历相簿中的全部图片

*  @param assetCollection 相簿

*  @param original        是否要原图

*/

-(void)getLibarayPhotoImage01{

    __weaktypeof(self) weakSelf =self;

    NSMutableArray *images = [NSMutableArray array];

    //获取可访问的图片配置选项

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

    //根据图片的创建时间升序排序返回

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

    //获取类型为image的资源

    PHFetchResult *result = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:option];

     //遍历出每个PHAsset资源对象

    [resultenumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

        PHAsset*asset = (PHAsset*)obj;

        //将PHAsset解析为image的配置选项

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

        //图像缩放模式

        requestOptions.resizeMode = PHImageRequestOptionsResizeModeExact;

        //图片质量

        requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;

        //PHImageManager解析图片

        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {

            NSLog(@"图片 %@",result);

            //在这里可以自定义一个显示可访问相册资源的viewController.

            if(result) {

                [weakSelf.photoArrayaddObject:result];

            }

        }];

        dispatch_async(dispatch_get_main_queue(), ^{

            [self.collectionView reloadData];

        });

    }];


}

-(void)getLibarayPhotoImage{


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        PHFetchResult *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];

        for(PHAssetCollection*assetCollectioninassetCollections) {

            [self enumerateAssetsInAssetCollection:assetCollection original:YES];

        }


        PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;

        [self enumerateAssetsInAssetCollection:cameraRoll original:YES];

    });


}

- (void)enumerateAssetsInAssetCollection:(PHAssetCollection *)assetCollectionoriginal:(BOOL)original

{

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

   options.resizeMode = PHImageRequestOptionsResizeModeFast;

   options.synchronous=YES;

   PHFetchResult *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];

   for(PHAsset*assetinassets) {

       CGSize size = original ? CGSizeMake(asset.pixelWidth, asset.pixelHeight) : CGSizeZero;

       __weaktypeof(self) weakSelf =self;

       [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {

           NSLog(@"%@", result);

           if(result) {

               original ? [weakSelf.photoArrayaddObject:result] : [weakSelf.photoArrayaddObject:result];

           }

       }];

       dispatch_async(dispatch_get_main_queue(), ^{

           [weakSelf.collectionViewreloadData];

       });

   }

}

#pragma mark--懒加载

- (UICollectionView *)collectionView{

    if (!_collectionView) {

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

        flowLayout.minimumLineSpacing=2;

        flowLayout.minimumInteritemSpacing = 1;

        UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:flowLayout];

        collectionView.backgroundColor = self.view.backgroundColor;

        collectionView.delegate=self;

        collectionView.dataSource=self;

        [collectionViewregisterClass:GDPickerCollectionViewCell.class forCellWithReuseIdentifier:NSStringFromClass(GDPickerCollectionViewCell.class)];

        _collectionView= collectionView;

    }

    return _collectionView;

}

@end

上面是PHAuthorizationStatusLimited 用户已授权此应用程序进行有限照片库访问(iOS14新增)的适配,下面在来说一下适配允许访问所有图片,下面是适配代码

//ios14后使用

-(void)P_enterPHPickerViewController{

    MJWeakSelf;

    //用户选择"允许访问所有照片",调用PHPickerViewController显示图片选择器

    dispatch_async(dispatch_get_main_queue(), ^{

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

        //只获取image类型资源

        configuration.filter = [PHPickerFilter imagesFilter];

         //可以多选

//        configuration.selectionLimit = 1;

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

        pickerVC.delegate=self;

        pickerVC.modalPresentationStyle = UIModalPresentationFullScreen;

        [weakSelf.controller presentViewController:pickerVC animated:YES completion:^{

        }];

    });

}


- (void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray *)results

{

    MJWeakSelf;

    [pickerdismissViewControllerAnimated:YES completion:nil];

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

        return;

    }

    NSLog(@"didFinishPicking");

    NSItemProvider *itemProvider = results.firstObject.itemProvider;

         if ([itemProvider canLoadObjectOfClass:UIImage.class]) {

             __weaktypeof(self) weakSelf =self;

             [itemProviderloadObjectOfClass:UIImage.class completionHandler:^(__kindof id  _Nullable object, NSError * _Nullable error) {

                 if([objectisKindOfClass:UIImage.class]) {

                     UIImage*image = (UIImage*)object;

                     [weakSelfanalysisImageWithContent:image];

                 }

             }];

         }

}

你可能感兴趣的:(iOS 14适配相册权限)