iOS开发中权限再度梳理

前言

上篇文章iOS开发中的这些权限,你搞懂了吗?介绍了一些常用权限的获取和请求方法,知道这些方法的使用基本上可以搞定大部分应用的权限访问的需求。但是,这些方法并不全面,不能涵盖住所有权限访问的方法。

So,笔者在介绍一下剩下的几种权限的访问方法和一些使用上的注意事项,希望能给大家的开发过程带来一丝便利。

最后,笔者将经常使用的权限请求方法封装开源库JLAuthorizationManager送给大家,欢迎大家pull request 和 star~~

权限

  • 语音识别
  • 媒体资料库/Apple Music
  • Siri
  • 健康数据共享
  • 蓝牙
  • 住宅权限(HomeKit)
  • 社交账号体系权限
  • 活动与体能训练记录
  • 广告标识

语音识别

引入头文件: @import Speech;

首先判断当前应用所处的权限状态,若当前状态为NotDetermined(未确定),此时,需要调用系统提供的请求权限方法,同时也是触发系统弹窗的所在点;

该权限涉及到的类为 SFSpeechRecognizer,具体代码如下:


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

- (void)p_requestSpeechRecognizerAccessWithAuthorizedHandler:(void(^)())authorizedHandler

                                         unAuthorizedHandler:(void(^)())unAuthorizedHandler{

    SFSpeechRecognizerAuthorizationStatus authStatus = [SFSpeechRecognizer authorizationStatus];

    if (authStatus == SFSpeechRecognizerAuthorizationStatusNotDetermined) {

         //调用系统提供的权限访问的方法

        [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) {

            if (status == SFSpeechRecognizerAuthorizationStatusAuthorized) {

                dispatch_async(dispatch_get_main_queue(), ^{

                     //授权成功后

                    authorizedHandler ? authorizedHandler() : nil;

                });

            }else{

                dispatch_async(dispatch_get_main_queue(), ^{

                    //授权失败后

                    unAuthorizedHandler ? unAuthorizedHandler() : nil;

                });

            }

        }];

    }else if (authStatus == SFSpeechRecognizerAuthorizationStatusAuthorized){

        authorizedHandler ? authorizedHandler() : nil;

    }else{

        unAuthorizedHandler ? unAuthorizedHandler() : nil;

    }

}

需要注意的是,调用requestAuthorization方法的block回调是在任意的子线程中进行的,如果你需要在授权成功后刷新UI的话,需要将对应的方法置于主线程中进行,笔者将上述方法默认在主线程中进行。后续权限请求方法与此类似,不再赘述。

在info.plist添加指定的配置信息,如下所示:

Speech Recognizer

媒体资料库/Apple Music

导入头文件@import MediaPlayer;

使用类MPMediaLibrary进行权限访问,代码如下;


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

- (void)p_requestAppleMusicAccessWithAuthorizedHandler:(void(^)())authorizedHandler

                                   unAuthorizedHandler:(void(^)())unAuthorizedHandler{

    MPMediaLibraryAuthorizationStatus authStatus = [MPMediaLibrary authorizationStatus];

    if (authStatus == MPMediaLibraryAuthorizationStatusNotDetermined) {

        [MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus status) {

            if (status == MPMediaLibraryAuthorizationStatusAuthorized) {

                dispatch_async(dispatch_get_main_queue(), ^{

                    authorizedHandler ? authorizedHandler() : nil;

                });

            }else{

                dispatch_async(dispatch_get_main_queue(), ^{

                    unAuthorizedHandler ? unAuthorizedHandler() : nil;

                });

            }

        }];

    }else if (authStatus == MPMediaLibraryAuthorizationStatusAuthorized){

         authorizedHandler ? authorizedHandler() : nil;

    }else{

        unAuthorizedHandler ? unAuthorizedHandler() : nil;

    }

}

在info.plist添加指定的配置信息,如下所示:

Media

Siri

导入头文件@import Intents;;

与其他权限不同的时,使用Siri需要在Xcode中Capabilities打开Siri开关,Xcode会自动生成一个xx.entitlements文件,若没有打开该开关,项目运行时会报错。

实现代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

- (void)p_requestSiriAccessWithAuthorizedHandler:(void(^)())authorizedHandler

                             unAuthorizedHandler:(void(^)())unAuthorizedHandler{

    INSiriAuthorizationStatus authStatus = [INPreferences siriAuthorizationStatus];

    if (authStatus == INSiriAuthorizationStatusNotDetermined) {

        [INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) {

            if (status == INSiriAuthorizationStatusAuthorized) {

                dispatch_async(dispatch_get_main_queue(), ^{

                     authorizedHandler ? authorizedHandler() : nil;

                });

            }else{

                dispatch_async(dispatch_get_main_queue(), ^{

                    unAuthorizedHandler ? unAuthorizedHandler() : nil;

                });

            }

        }];

    }else if (authStatus == INSiriAuthorizationStatusAuthorized){

        authorizedHandler ? authorizedHandler() : nil;

    }else{

        unAuthorizedHandler ? unAuthorizedHandler() : nil;

    }

}

健康数据共享

导入头文件@import HealthKit;

健康数据共享权限相对其他权限相对复杂一些,分为写入和读出权限.

在Xcode 8中的info.plist需要设置以下两种权限:


1

2

1、Privacy - Health Update Usage Description

2、Privacy - Health Share Usage Description

具体实现代码:


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

//设置写入/共享的健康数据类型

- (NSSet *)typesToWrite {

    HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];

    return [NSSet setWithObjects:stepType,distanceType, nil];

}

//设置读写以下为设置的权限类型:

- (NSSet *)typesToRead {

   HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

    HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];

    return [NSSet setWithObjects:stepType,distanceType, nil];

}

//需要确定设备支持HealthKit

if ([HKHealthStore isHealthDataAvailable]) {

        return;

    }

HKHealthStore *healthStore = [[HKHealthStore alloc] init];

    NSSet * typesToShare = [self typesToWrite];

    NSSet * typesToRead = [self typesToRead];

    [healthStore requestAuthorizationToShareTypes:typesToShare readTypes:typesToRead completion:^(BOOL success, NSError * _Nullable error) {

        if (success) {

            dispatch_async(dispatch_get_main_queue(), ^{

                NSLog(@"Health has authorized!");

            });

        }else{

            dispatch_async(dispatch_get_main_queue(), ^{

                NSLog(@"Health has not authorized!");

            });

        }

    }];

蓝牙

需要导入头文件@import CoreBluetooth;

蓝牙的权限检测相对其他会复杂一些,需要在代理中检测蓝牙状态;

获取蓝牙权限:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

- (void)checkBluetoothAccess {

    CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

    CBManagerState state = [cbManager state];

    if(state == CBManagerStateUnknown) {

        NSLog(@"Unknown!");

    }

    else if(state == CBManagerStateUnauthorized) {

         NSLog(@"Unauthorized!");

    }

    else {

        NSLog(@"Granted!");

    }

}

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {

//这个代理方法会在蓝牙权限状态发生变化时被调用,并且可以根据不同的状态进行相应的修改UI或者数据访问的操作。

}

请求蓝牙权限


1

2

3

4

5

- (void)requestBluetoothAccess {

    CBCentralManager *cbManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

//该方法会显示用户同意的弹窗

    [cbManager scanForPeripheralsWithServices:nil options:nil];

}

住宅权限(HomeKit)

需导入头文件@import HomeKit;

HomeKit请求权限的方法如下:


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

- (void)requestHomeAccess {

    self.homeManager = [[HMHomeManager alloc] init];

//当设置该代理方法后,会请求用户权限

    self.homeManager.delegate = self;

}

- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager {

    if (manager.homes.count > 0) {

        // home的数量不为空,即表示用户权限已通过

    }

    else {

        __weak HMHomeManager *weakHomeManager = manager; // Prevent memory leak

        [manager addHomeWithName:@"Test Home" completionHandler:^(HMHome *home, NSError *error) {

            if (!error) {

               //权限允许

            }

            else {

                if (error.code == HMErrorCodeHomeAccessNotAuthorized) {

                   //权限不允许

                }

                else {

                    //处理请求产生的错误

                }

            }

            if (home) {

                [weakHomeManager removeHome:home completionHandler:^(NSError * _Nullable error) {

                    //移除Home

                }];

            }

        }];

    }

}

社交账号体系权限

导入头文件@import Accounts;

获取对应的权限:


1

2

3

4

5

6

7

8

9

10

- (void)checkSocialAccountAuthorizationStatus:(NSString *)accountTypeIndentifier {

    ACAccountStore *accountStore = [[ACAccountStore alloc] init];

    ACAccountType *socialAccount = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIndentifier];

    if ([socialAccount accessGranted]) {

        NSLog(@"权限通过了");

    }else{

         NSLog(@"权限未通过!");

 }

}

accountTypeIndentifier 可以是以下类型:


1

2

3

4

5

ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierTwitter NS_AVAILABLE(NA, 5_0);

ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierFacebook NS_AVAILABLE(NA, 6_0);

ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierSinaWeibo NS_AVAILABLE(NA, 6_0);

ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierTencentWeibo NS_AVAILABLE(NA, 7_0);

ACCOUNTS_EXTERN NSString * const ACAccountTypeIdentifierLinkedIn NS_AVAILABLE(NA, NA);

请求对应的权限:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

- (void)requestTwitterAccess {

    ACAccountStore *accountStore = [[ACAccountStore alloc] init];

    ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:accountTypeIdentifier];

    

    [accountStore requestAccessToAccountsWithType: accountType options:nil completion:^(BOOL granted, NSError *error) {

        dispatch_async(dispatch_get_main_queue(), ^{

           if(granted){

                 NSLog(@"授权通过了");

            }else{

                 NSLog(@"授权未通过");

            }

        });

    }];

}

活动与体能训练记录

导入头文件@import CoreMotion;

具体实现代码:


1

2

3

4

5

6

7

//访问活动与体能训练记录

    CMMotionActivityManager *cmManager = [[CMMotionActivityManager alloc] init];

    NSOperationQueue *queue = [[NSOperationQueue alloc] init];

    [cmManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *activity) {

    

        //授权成功后,会进入Block方法内,授权失败不会进入Block方法内

    }];

广告标识

导入头文件@import AdSupport;

获取广告标识的权限状态:


1

BOOL isAuthorizedForAd = [[ASIdentifierManager sharedManager] isAdvertisingTrackingEnabled];

在使用advertisingIdentifier属性前,必须调用上述方法判断是否支持,如果上述方法返回值为NO,则advertising ID访问将会受限。

小结一下

通过以上两篇文章的整理,有关iOS系统权限问题的处理基本上涵盖完全了;

并不是所有的权限访问都有显式的调用方法,有些是在使用过程中进行访问的,比如定位权限、蓝牙共享权限、Homekit权限、活动与体能训练权限,这些权限在使用时注意回调方法中的权限处理;

HomeKit、HealthKit、Siri需要开启Capabilities中的开关,即生成projectName.entitlements文件;

开源库JLAuthorizationManager支持集成大部分常用的权限访问,便捷使用 welcome to pull request or star

时间: 2024-11-06 07:32:44

iOS开发中权限再度梳理的相关文章

再续iOS开发中的这些权限

前言 上篇文章iOS开发中的这些权限,你搞懂了吗?介绍了一些常用权限的获取和请求方法,知道这些方法的使用基本上可以搞定大部分应用的权限访问的需求.但是,这些方法并不全面,不能涵盖住所有权限访问的方法. So,笔者在介绍一下剩下的几种权限的访问方法和一些使用上的注意事项,希望能给大家的开发过程带来一丝便利. 最后,笔者将经常使用的权限请求方法封装开源库JLAuthorizationManager送给大家,欢迎大家pull request 和 star~~ 权限 语音识别: 媒体资料库/Apple

ios开发中遇到的问题和解答汇总

如何让一个数组中的字典,如果字典中有重复的id.将重复的id的字典进行数组整合....<点击查看详情>iOS UIView 创建是不是都会经过initWithFrame?<点击查看详情>iPad 9.1系统上键盘响应很慢<点击查看详情>ios如何绑定数据?<点击查看详情>iOS开发,我想上传一个.gsd的文件(或者stl),请问该怎么做<点击查看详情>iOS NSTimer问题<点击查看详情>iOS大部分积分墙软件为啥都做基于Safa

iOS开发中UIPopoverController的使用详解

这篇文章主要介绍了iOS开发中UIPopoverController的使用,代码基于传统的Objective-C,需要的朋友可以参考下 一.简单介绍 1.什么是UIPopoverController 是iPad开发中常见的一种控制器(在iPhone上不允许使用) 跟其他控制器不一样的是,它直接继承自NSObject,并非继承自UIViewController 它只占用部分屏幕空间来呈现信息,而且显示在屏幕的最前面 2.使用步骤 要想显示一个UIPopoverController,需要经过下列步骤

iOS开发中一些有用的小代码

1.判断邮箱格式是否正确的代码: //利用正则表达式验证 -(BOOL)isValidateEmail:(NSString *)email { NSString *emailRegex = @"[A-Z0-9a-z._%+-][email protected][A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES%@&qu

IOS开发中使用CNContact对通讯录增删改查

IOS开发中使用CNContact对通讯录增删改查 首先当然是把CNcontact包含在工程中: 1 @import Contacts; 1.下面是增加联系人的程序段: 1 CNMutableContact * contact = [[CNMutableContact alloc]init]; 2 contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"22"]); 3 //设置名字 4 contact.gi

ios开发中-AFNetworking 的简单介绍

Blog: Draveness 关注仓库,及时获得更新: iOS-Source-Code-Analyze 在这一系列的文章中,我会对 AFNetworking 的源代码进行分析,深入了解一下它是如何构建的,如何在日常中完成发送 HTTP 请求.构建网络层这一任务. AFNetworking 是如今 iOS 开发中不可缺少的组件之一.它的 github 配置上是如下介绍的: Perhaps the most important feature of all, however, is the ama

iOS 开发中用户记住账户,密码

在iOS开发中经常会用到记住账户.密码,以此来提高用户的体验.下面就浅谈一下账户.密码的存储. 一.登录 记录已登录用户步骤,存入偏好设置中存储放入一个数组. 具体存储 1:存储用户到偏好设置中,其中用户是一个数组向服务器响应客户端后的一些操作(如果响应数据成功)其中用户和密码是一一对应的 1.1先从沙盒中偏好设置中读取对应的用户集合 读取用户名: NSMutableArray *AccArys = [NSMutableArray arrayWithArray:[[NSUserDefaults

iOS开发中KVC、KVO简介

在iOS开发中,KVC和KVO是经常被用到的.可以使用KVC对对象的属性赋值和取得对象的属性值,可以使用KVO监听对象属性值的变化.简单介绍一下KVC和KVO. 一:键值编码(KVC) KVC,全称 Key Value Coding(键值编码),是OC 语言的一个特性,使用KVC,可以对对象的属性进行动态读写. KVC的操作方法由 NSKeyValueCoding协议提供,而NSObject已经实现了这个协议,因此OC中的几乎所有对象都可以使用KVC操作.常用的KVC操作方法有: (1)设置属性

iOS开发中打电话发短信等功能的实现

在APP开发中,可能会涉及到打电话.发短信.发邮件等功能.比如说,通常一个产品的“关于”页面,会有开发者的联系方式,理想情况下,当用户点击该电话号码时,能够自动的帮用户拨出去,就涉及到了打电话的功能. iOS开发中,有三种方式可以打电话: (1)直接跳到拨号界面,代码如下 1 2 NSURL *url = [NSURL URLWithString:@"tel://10010"];  [[UIApplication sharedApplication] openURL:url]; 缺点: