iOS相册、相机、通讯录权限获取

本文详细介绍了iOS应用程序中如何处理相册、相机和通讯录等敏感权限的请求与管理,包括不同iOS版本间的API差异及封装示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、为什么要获取权限

在越来越注重个人隐私的今天,用户很多情况下希望自己能完全掌握自己手机应用对媒体信息的一些访问权限,比如相册、相机、通讯录等。苹果在iOS7、iOS8等几个系统版本对一些权限的控制都做了加强,需要用户授权后应用才有相关的访问权限。

场景:

  • 在你获取相册数据的时候,如果用户拒绝授权,那么可能会获取不到数据,此时需要给用户相应的提示,告知用户是权限的问题,此时,就需要得知相应的权限状态给用户恰当的提示。

  • 用户的设备没有相机输入设备,如果你想访问用户的相机,此时就需要判断用户设备是否支持,给出恰当的提示。

二、权限状态说明

  • 相册、相机、通讯录等授权状态目前都有种,都可以对应以下几种状态:

    AuthorizationStatusNotDetermined      // 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权
    AuthorizationStatusAuthorized = 0,    // 用户已授权,允许访问
    AuthorizationStatusDenied,            // 用户拒绝访问
    AuthorizationStatusRestricted,        // 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制
       
    • 1
    • 2
    • 3
    • 4

三、权限获取

  1. 相册权限

    • 是否支持

      [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]
           
      • 1
    • 获取权限状态 

      ios8以前

          ALAuthorizationStatus authStatus = [ALAssetsLibrary authorizationStatus];
           
      • 1

      ios8及以后

          PHAuthorizationStatus authStatus = [PHPhotoLibrary authorizationStatus];
           
      • 1
    • 请求权限

      [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                      }];
           
      • 1
      • 2
    • 权限状态

      iOS8以前

      typedef NS_ENUM(NSInteger, ALAuthorizationStatus) {
          ALAuthorizationStatusNotDetermined NS_ENUM_DEPRECATED_IOS(6_0, 9_0) = 0, // User has not yet made a choice with regards to this application
          ALAuthorizationStatusRestricted NS_ENUM_DEPRECATED_IOS(6_0, 9_0),        // This application is not authorized to access photo data.
                                                  // The user cannot change this application’s status, possibly due to active restrictions
                                                  //  such as parental controls being in place.
          ALAuthorizationStatusDenied NS_ENUM_DEPRECATED_IOS(6_0, 9_0),            // User has explicitly denied this application access to photos data.
          ALAuthorizationStatusAuthorized NS_ENUM_DEPRECATED_IOS(6_0, 9_0)        // User has authorized this application to access photos data.
      } NS_DEPRECATED_IOS(6_0, 9_0, "Use PHAuthorizationStatus in the Photos framework instead");
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      iOS8及以后

      typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
          PHAuthorizationStatusNotDetermined = 0, // User has not yet made a choice with regards to this application
          PHAuthorizationStatusRestricted,        // This application is not authorized to access photo data.
                                                  // The user cannot change this application’s status, possibly due to active restrictions
                                                  //   such as parental controls being in place.
          PHAuthorizationStatusDenied,            // User has explicitly denied this application access to photos data.
          PHAuthorizationStatusAuthorized         // User has authorized this application to access photos data.
      } NS_AVAILABLE_IOS(8_0);
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
  2. 拍照权限

    • 是否支持

      [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]
           
      • 1
    • 获取权限状态

      AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
           
      • 1
    • 请求权限

      [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                      }];
           
      • 1
      • 2
    • 权限状态

      typedef NS_ENUM(NSInteger, AVAuthorizationStatus) {
          AVAuthorizationStatusNotDetermined = 0,
          AVAuthorizationStatusRestricted,
          AVAuthorizationStatusDenied,
          AVAuthorizationStatusAuthorized
      } NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
  3. 通讯录权限

    • 获取权限状态

      iOS9以前

      ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
           
      • 1

      iOS9及以后

      CNAuthorizationStatus authStatus = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
           
      • 1
    • 请求权限

      iOS9以前

      __block ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
      if (addressBook == NULL) {
          [self executeCallback:callback status:WTAuthorizationStatusNotSupport];
          return;
      }
      ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
          if (granted) {
              // 成功
          } else {
              // 失败
          }
          if (addressBook) {
              CFRelease(addressBook);
              addressBook = NULL;
          }
      });
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      iOS9及以后

      CNContactStore *contactStore = [[CNContactStore alloc] init];
      [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
          if (granted) {
              // 成功
          } else {
              // 失败
          }
      }];
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
    • 权限状态

      iOS9以前

      typedef CF_ENUM(CFIndex, ABAuthorizationStatus) {
          kABAuthorizationStatusNotDetermined = 0,    // deprecated, use CNAuthorizationStatusNotDetermined
          kABAuthorizationStatusRestricted,           // deprecated, use CNAuthorizationStatusRestricted
          kABAuthorizationStatusDenied,               // deprecated, use CNAuthorizationStatusDenied
          kABAuthorizationStatusAuthorized            // deprecated, use CNAuthorizationStatusAuthorized
      } AB_DEPRECATED("use CNAuthorizationStatus");
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      iOS9及以后

      typedef NS_ENUM(NSInteger, CNAuthorizationStatus)
      {
      /*! The user has not yet made a choice regarding whether the application may access contact data. */
      CNAuthorizationStatusNotDetermined = 0,
      /*! The application is not authorized to access contact data.
      *  The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place. */
      CNAuthorizationStatusRestricted,
      /*! The user explicitly denied access to contact data for the application. */
      CNAuthorizationStatusDenied,
      /*! The application is authorized to access contact data. */
      CNAuthorizationStatusAuthorized
      } NS_ENUM_AVAILABLE(10_11, 9_0);
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

四、拒绝授权的处理

  • 用户拒绝授权后,如果访问相应内容可能会出现一些类似没有数据的情况,此时应该给用户提示,引导用户授权。

    跳转到应用设置:

    NSURL *settingUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
    if ([[UIApplication sharedApplication] canOpenURL:settingUrl]) {
        [[UIApplication sharedApplication] openURL:settingUrl];
    }
       
    • 1
    • 2
    • 3
    • 4

五、简单封装示例

  • 工具类

    WTAuthorizationTool.h文件

    
    #import <Foundation/Foundation.h>
    
    
    typedef NS_ENUM(NSUInteger, WTAuthorizationStatus) {
        WTAuthorizationStatusAuthorized = 0,    // 已授权
        WTAuthorizationStatusDenied,            // 拒绝
        WTAuthorizationStatusRestricted,        // 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制
        WTAuthorizationStatusNotSupport         // 硬件等不支持
    };
    
    @interface WTAuthorizationTool : NSObject
    
    /**
     *  请求相册访问权限
     *
     *  @param callback <#callback description#>
     */
    + (void)requestImagePickerAuthorization:(void(^)(WTAuthorizationStatus status))callback;
    
    /**
     *  请求相机权限
     *
     *  @param callback <#callback description#>
     */
    + (void)requestCameraAuthorization:(void(^)(WTAuthorizationStatus status))callback;
    
    + (void)requestAddressBookAuthorization:(void (^)(WTAuthorizationStatus))callback;
    
    @end
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    WTAuthorizationTool.m文件

    
    #import "WTAuthorizationTool.h"
    
    
    
    #import <AssetsLibrary/AssetsLibrary.h>
    
    
    #import <Photos/Photos.h>
    
    
    #import <AddressBook/AddressBook.h>
    
    
    #import <AddressBookUI/AddressBookUI.h>
    
    
    #import <ContactsUI/ContactsUI.h>
    
    
    @implementation WTAuthorizationTool
    
    
    #pragma mark - 相册
    
    + (void)requestImagePickerAuthorization:(void(^)(WTAuthorizationStatus status))callback {
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ||
            [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
            ALAuthorizationStatus authStatus = [ALAssetsLibrary authorizationStatus];
            if (authStatus == ALAuthorizationStatusNotDetermined) { // 未授权
                if ([UIDevice currentDevice].systemVersion.floatValue < 8.0) {
                    [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
                } else {
                    [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                        if (status == PHAuthorizationStatusAuthorized) {
                            [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
                        } else if (status == PHAuthorizationStatusDenied) {
                            [self executeCallback:callback status:WTAuthorizationStatusDenied];
                        } else if (status == PHAuthorizationStatusRestricted) {
                            [self executeCallback:callback status:WTAuthorizationStatusRestricted];
                        }
                    }];
                }
    
            } else if (authStatus == ALAuthorizationStatusAuthorized) {
                [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
            } else if (authStatus == ALAuthorizationStatusDenied) {
                [self executeCallback:callback status:WTAuthorizationStatusDenied];
            } else if (authStatus == ALAuthorizationStatusRestricted) {
                [self executeCallback:callback status:WTAuthorizationStatusRestricted];
            }
        } else {
            [self executeCallback:callback status:WTAuthorizationStatusNotSupport];
        }
    }
    
    
    #pragma mark - 相机
    
    + (void)requestCameraAuthorization:(void (^)(WTAuthorizationStatus))callback {
        if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
            if (authStatus == AVAuthorizationStatusNotDetermined) {
                [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
                    if (granted) {
                        [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
                    } else {
                        [self executeCallback:callback status:WTAuthorizationStatusDenied];
                    }
                }];
            } else if (authStatus == AVAuthorizationStatusAuthorized) {
                [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
            } else if (authStatus == AVAuthorizationStatusDenied) {
                [self executeCallback:callback status:WTAuthorizationStatusDenied];
            } else if (authStatus == AVAuthorizationStatusRestricted) {
                [self executeCallback:callback status:WTAuthorizationStatusRestricted];
            }
        } else {
            [self executeCallback:callback status:WTAuthorizationStatusNotSupport];
        }
    }
    
    
    #pragma mark - 通讯录
    
    + (void)requestAddressBookAuthorization:(void (^)(WTAuthorizationStatus))callback {
        ABAuthorizationStatus authStatus = ABAddressBookGetAuthorizationStatus();
        if (authStatus == kABAuthorizationStatusNotDetermined) {
            __block ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
            if (addressBook == NULL) {
                [self executeCallback:callback status:WTAuthorizationStatusNotSupport];
                return;
            }
            ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
                if (granted) {
                    [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
                } else {
                    [self executeCallback:callback status:WTAuthorizationStatusDenied];
                }
                if (addressBook) {
                    CFRelease(addressBook);
                    addressBook = NULL;
                }
            });
            return;
        } else if (authStatus == kABAuthorizationStatusAuthorized) {
            [self executeCallback:callback status:WTAuthorizationStatusAuthorized];
        } else if (authStatus == kABAuthorizationStatusDenied) {
            [self executeCallback:callback status:WTAuthorizationStatusDenied];
        } else if (authStatus == kABAuthorizationStatusRestricted) {
            [self executeCallback:callback status:WTAuthorizationStatusRestricted];
        }
    }
    
    
    #pragma mark - callback
    
    + (void)executeCallback:(void (^)(WTAuthorizationStatus))callback status:(WTAuthorizationStatus)status {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (callback) {
                    callback(status);
            }
        });
    }
    
    @end
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
  • 界面测试提示

    controller部分代码

    - (void)requestAddressBook {
        [WTAuthorizationTool requestAddressBookAuthorization:^(WTAuthorizationStatus status) {
            [self requestAuthCallback:status];
        }];
    }
    
    - (void)requestCamera {
        [WTAuthorizationTool requestCameraAuthorization:^(WTAuthorizationStatus status) {
            [self requestAuthCallback:status];
        }];
    }
    
    - (void)requestAlbum {
        [WTAuthorizationTool requestImagePickerAuthorization:^(WTAuthorizationStatus status) {
            [self requestAuthCallback:status];
        }];
    }
    
    - (void)requestAuthCallback:(WTAuthorizationStatus)status {
        switch (status) {
            case WTAuthorizationStatusAuthorized:
                [WTAlert showAlertFrom:self title:@"授权成功" message:@"可以访问你要访问的内容了" cancelButtonTitle:@"我知道了" cancle:^{
    
                } confirmButtonTitle:nil confirm:nil];
                break;
    
            case WTAuthorizationStatusDenied:
            case WTAuthorizationStatusRestricted:
                [WTAlert showAlertFrom:self title:@"授权失败" message:@"用户拒绝" cancelButtonTitle:@"我知道了" cancle:^{
    
                } confirmButtonTitle:@"现在设置" confirm:^{
                    NSURL *settingUrl = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                    if ([[UIApplication sharedApplication] canOpenURL:settingUrl]) {
                        [[UIApplication sharedApplication] openURL:settingUrl];
                    }
                }];
                break;
    
            case WTAuthorizationStatusNotSupport:
                [WTAlert showAlertFrom:self title:@"授权失败" message:@"设备不支持" cancelButtonTitle:@"我知道了" cancle:^{
    
                } confirmButtonTitle:nil confirm:nil];
    
            default:
                break;
        }
    }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

六、源码

完整源码

  • 使用WTAuthorizationTool

    pod "WTAuthorizationTool"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值