iOS   开发权限

APP开发避免不开系统权限的问题,今天做定位时需要在不允许定位的时候做一些操作,所以,今天就大概的了解了一些。

权限分类

升到iOS10之后,需要设置权限的有:
麦克风权限:Privacy - Microphone Usage Description 是否允许此App使用你的麦克风?
相机权限: Privacy - Camera Usage Description 是否允许此App使用你的相机?
相册权限: Privacy - Photo Library Usage Description 是否允许此App访问你的媒体资料库?
通讯录权限: Privacy - Contacts Usage Description 是否允许此App访问你的通讯录?
蓝牙权限:Privacy - Bluetooth Peripheral Usage Description 是否许允此App使用蓝牙?
语音转文字权限:Privacy - Speech Recognition Usage Description 是否允许此App使用语音识别?
日历权限:Privacy - Calendars Usage Description
定位权限:Privacy - Location When In Use Usage Description
定位权限: Privacy - Location Always Usage Description
位置权限:Privacy - Location Usage Description
媒体库权限:Privacy - Media Library Usage Description
健康分享权限:Privacy - Health Share Usage Description
健康更新权限:Privacy - Health Update Usage Description
运动使用权限:Privacy - Motion Usage Description
音乐权限:Privacy - Music Usage Description
提醒使用权限:Privacy - Reminders Usage Description
Siri使用权限:Privacy - Siri Usage Description
电视供应商使用权限:Privacy - TV Provider Usage Description
视频用户账号使用权限:Privacy - Video Subscriber Account Usage Description

【联网权限】

在iOS 10下 ,首次进入应用时,会有询问是否允许网络连接权限的的弹窗,为更好进行用户交互,需要在打开应用时获取应用禁用网络权限状态(状态分为:未知、限制网络、未限制网络),客户端根据不同的权限状态定制相应的人机交互。

针对请求应用网络权限可能存在的几种情形:

关闭 Restricted
无线局域网 NotRestricted
无线局域网&蜂窝 NotRestricted
不进行操作 Unknown

使用 CoreTelephony.framework 框架下的 CTCellularData 类中的方法和属性进行解决
需要先导入#import <CoreTelephony/CTCellularData.h>

应用启动后,检测应用中是否有联网权限
CTCellularData *cellularData = [[CTCellularData alloc]init];
cellularData.cellularDataRestrictionDidUpdateNotifier =  ^(CTCellularDataRestrictedState state){
  //获取联网状态
  switch (state) {
        case kCTCellularDataRestricted:
                  NSLog(@"Restricrted");          
                  break;
        case kCTCellularDataNotRestricted:
                  NSLog(@"Not Restricted");          
                  break;
        case kCTCellularDataRestrictedStateUnknown:
                  NSLog(@"Unknown");          
                  break;
        default:
            break;
  };
};
查询应用是否有联网功能
CTCellularData *cellularData = [[CTCellularData alloc]init];
CTCellularDataRestrictedState state = cellularData.restrictedState;
 switch (state) {
   case kCTCellularDataRestricted:
         NSLog(@"Restricrted");      
         break;
   case kCTCellularDataNotRestricted:
         NSLog(@"Not Restricted");      
         break;  
   case kCTCellularDataRestrictedStateUnknown:
         NSLog(@"Unknown");      
         break;
   default:
         break;
}

不幸的是,苹果这个功能可能出得太仓促,并没有给开发者提供相应的 API。所以,我们没办法检测到用户点击“允许”或“不允许”网络请求的回调,也没法检测到当前用户是否授权的状态。

【相册权限】

iOS8以后,第一次访问系统设备的一些属性时,比如相册,照相机,定位等,都会接收系统的权限访问,这个访问并不能使用代码跳过,而在系统的settings里面得隐私设置,可以设置某个程序对系统设备属性的访问权限,而我们能做的就是通过AVCaptureDevice来获取AVAuthorizationStatus属性,判断一下当前的权限,防止在不允许的情况下有Bug!

需要导入#import <Photos/Photos.h>这个头文件
这个方法判断是否允许使用相册的回调
 [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
  if (status == PHAuthorizationStatusAuthorized) {
      //允许使用相册
  }else{
  //不允许使用相册
 }
  }];
相册权限
PHAuthorizationStatus photoAuthorStatus = [PHPhotoLibrary authorizationStatus];
switch (photoAuthorStatus) {
  case PHAuthorizationStatusAuthorized:
      NSLog(@"允许授权");
      break;
  case PHAuthorizationStatusDenied:
      NSLog(@"不允许授权");
      break;
  case PHAuthorizationStatusNotDetermined:
      NSLog(@"不确定");
      break;
  case PHAuthorizationStatusRestricted:
      NSLog(@"限制");
      break;
  default:
      break;
}

在使用相册的时候,需要在plist文件中做一些设置


屏幕快照 2016-12-23 下午6.56.48.png

【相机和麦克风权限】

需要导入#import <AVFoundation/AVFoundation.h>
相机对应AVMediaTypeVideo
麦克风对应AVMediaTypeAudio

权限类型
typedef NS_ENUM(NSInteger, AVAuthorizationStatus) {
  AVAuthorizationStatusNotDetermined = 0,// 未询问用户是否授权
  AVAuthorizationStatusRestricted,// 未授权,例如家长控制
  AVAuthorizationStatusDenied,// 未授权,用户拒绝造成的
  AVAuthorizationStatusAuthorized// 已授权}
权限检测
AVAuthorizationStatus videoAuthStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
  if (videoAuthStatus == AVAuthorizationStatusNotDetermined) {// 未询问用户是否授权
  }else if(videoAuthStatus == AVAuthorizationStatusRestricted || videoAuthStatus == AVAuthorizationStatusDenied) {// 未授权
  }else{// 已授权
  }
请求授权
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {

      if (granted){// 用户同意授权

      }else {// 用户拒绝授权

      }

}];

【定位权限】

导入类库

#import <CoreLocation/CLLocationManager.h>

一些枚举值

这里就要查看CLLocationManager的授权状态,此方法会返回当前授权状态:
[CLLocationManager authorizationStatus]

授权状态为枚举值:
kCLAuthorizationStatusNotDetermined                  //用户尚未对该应用程序作出选择
kCLAuthorizationStatusRestricted                     //应用程序的定位权限被限制 
kCLAuthorizationStatusAuthorizedAlways               //一直允许获取定位
kCLAuthorizationStatusAuthorizedWhenInUse            //在使用时允许获取定位
kCLAuthorizationStatusAuthorized                     //已废弃,相当于一直允许获取定位
kCLAuthorizationStatusDenied                         //拒绝获取定位

判断用户是否授权应用获取定位权限的完整代码:

if ([CLLocationManager locationServicesEnabled] && ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorizedWhenInUse || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined || [CLLocationManager authorizationStatus] == kCLAuthorizationStatusAuthorized)) {        

//定位功能可用

}else if ([CLLocationManager authorizationStatus] ==kCLAuthorizationStatusDenied) {

//定位不能用

}

跳转到设置->允许定位

 NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
  if ([[UIApplication sharedApplication] canOpenURL:url]) {
                [[UIApplication sharedApplication] openURL:url]      
      }

【推送权限】

检查是否有通讯权限
  UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];
switch (settings.types) {
  case UIUserNotificationTypeNone:
      
      break;
  case UIUserNotificationTypeAlert:
    
      break;
  case UIUserNotificationTypeBadge:
   
      break;
  case UIUserNotificationTypeSound:
 
      break;

  default:
      break;
}
获取推送权限
UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:setting];

【通信录权限】

在iOS8中我们访问通讯录用的还是ABAddressBookRef,现在苹果又更新了,推出了ContactsUI,据说比以前更好用,下面简单介绍一下用法

程序启动需要先请求授权
//判断是否已经授权
CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
if ( status == CNAuthorizationStatusAuthorized) {
//如果已经授权,直接返回
return;
}else{
//iOS8授权方式 
//创建通讯录
// ABAddressBookRef book = ABAddressBookCreateWithOptions(NULL, NULL);
//请求授权
// ABAddressBookRequestAccessWithCompletion(book, ^(bool granted, CFErrorRef error) {
// if (granted) {
// NSLog(@"授权成功");
// }else{
// NSLog(@"授权失败");
// }
// });
// [CNContactStore requestAccessForEntityType:completionHandler:]
//iOS9授权
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error) {
NSLog(@"error=%@",error);
}
if (granted) {
NSLog(@"授权成功");
}else{
NSLog(@"授权失败");
}

}]; 
} 

获取联系人界面

//获取联系人列表
- (IBAction)btn2Click:(id)sender {
CNContactPickerViewController *contactPickerVC = [[CNContactPickerViewController alloc] init];
contactPickerVC.delegate = self;//控制器实现CNContactPickerDelegate
[self presentViewController:contactPickerVC animated:YES completion:nil];

}
//CNContactPickerDelegate
//取消
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker{
[picker dismissViewControllerAnimated:YES completion:nil];
}
//不实现此方法,默认进入详细列表界面
/**点击联系人**/
//- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContact:(CNContact *)contact{
// NSLog(@"%@",contact.phoneNumbers[0]);
// 
//}
/**点击联系人某个属性**/
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty{

if ([contactProperty.value isKindOfClass:[CNPhoneNumber class]]) {
CNPhoneNumber *phoneNum = contactProperty.value;
NSLog(@"%@",phoneNum.stringValue);
}else{
NSLog(@"选择的不是手机号");
}

} 

跳转到系统的设置界面

在项目中,我们经常会碰到使用位置的需求。当用户设置app不允许使用位置的时候,最好的用户体验就是直接调转到系统的位置设置界面,进行设置。
电池电量 Prefs:root=BATTERY_USAGE
通用设置 Prefs:root=General
存储空间 Prefs:root=General&path=STORAGE_ICLOUD_USAGE/DEVICE_STORAGE
蜂窝数据 Prefs:root=MOBILE_DATA_SETTINGS_ID
Wi-Fi 设置 Prefs:root=WIFI
蓝牙设置 Prefs:root=Bluetooth
定位设置 Prefs:root=Privacy&path=LOCATION
辅助功能 Prefs:root=General&path=ACCESSIBILITY
关于手机 Prefs:root=General&path=About
键盘设置 Prefs:root=General&path=Keyboard
显示设置 Prefs:root=DISPLAY
声音设置 Prefs:root=Sounds
App Store 设置 Prefs:root=STORE
墙纸设置 Prefs:root=Wallpaper
打开电话 Mobilephone://
世界时钟 Clock-worldclock://
闹钟 Clock-alarm://
秒表 Clock-stopwatch://
倒计时 Clock-timer://
打开相册 Photos://

NSURL*url=[NSURL URLWithString:@"Prefs:root=Privacy&path=LOCATION"];
Class LSApplicationWorkspace = NSClassFromString(@"LSApplicationWorkspace");
[[LSApplicationWorkspace performSelector:@selector(defaultWorkspace)] performSelector:@selector(openSensitiveURL:withOptions:) withObject:url withObject:nil];

这个需要添加URL Scheme,方法:Target -> Info -> URL Types,点击“+”,将URL Schemes设置为Prefs即可。

20160105155212746.jpeg

上面那一个方法里面有一个performSelector的方法,因为我也不太明白,所以
在此我对performSelector系列方法进行了总结

- (id)performSelector:(SEL)aSelector;

- (id)performSelector:(SEL)aSelector withObject:(id)object;

- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

这三个方法都是同步执行,与线程无关,在需要动态的去调用方法的时候去使用。

例如:

[self performSelector:@selector(configUI)]; 与[self configUI]; 效果完全相同。

withObject:(id)object 这是要传递的参数

2、

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSString *> *)modes;

- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;

  这两个方法为异步执行,只能在主线程中执行。可用于点击UI中一个按钮会触发一个消耗性能的事件,在事件执行期间按钮会一直处于高亮状态,此时可以调用该方法去异步的处理该事件,避免上述问题。

在方法未到执行时间之前,取消方法为:

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullable id)anArgument;

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

调用该方法之前或在该方法所在的viewController生命周期结束的时候去调用取消函数,以确保不会引起内存泄露。

3、

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array;

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;

这两个方法,在主线程和子线程中均可执行,均会调用主线程的aSelector方法

如果设置wait为YES:等待当前线程执行完以后,主线程才会执行aSelector方法;

设置为NO:不等待当前线程执行完,就在主线程上执行aSelector方法。

如果,当前线程就是主线程,那么aSelector方法会马上执行。

注意:apple不允许程序员在主线程以外的线程中对ui进行操作,此时我们必须调用performSelectorOnMainThread函数在主线程中完成UI的更新

4、 

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray<NSString *> *)array NS_AVAILABLE(10_5, 2_0);

- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);

在我们指定的线程中调用方法。

5、

- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0);

后台执行

今天晚上平安夜,而且还是周六,我在这里找了一天,才整理出来这么一点。书写不易,点赞吧

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容