"Unable to retrieve CarrierName."CTError引发的对iOS系统权限的总结

来源:互联网 发布:mac双系统开机选择切换 编辑:程序博客网 时间:2024/04/29 11:55

之所以用这个error log作为title,是因为当这个log打出来时,着实让我有些“meng”,so就以这个作为标题,方便大家相同问题的检索吧;

问题描述和分析:

又是一个临时的小问题,先描述一下问题场景吧:

今天调试了一段地图,定位服务的代码,在添加MKMapView之后,我们初始化定位器,并获取定位权限;

if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {            [_locationManager requestWhenInUseAuthorization];        }        [_locationManager startUpdatingLocation];

我们都知道iOS10之后,苹果提供了更强大的隐私数据保护,简单来说就是在 访问用户数据时 都需要在info.plist中声明;

那如果不声明呢?

看见一些小伙伴在调试时遇到的crush,甚至在iTunes上提交二进制包时莫名其妙的看不见…………某家笑而不语^_^

配置之后貌似是这样:

启动程序,点击运行这段代码,log如下:

这是啥??!

网上搜了搜,无果;查了下API也没明白……姑且不过这个log,实际的运行结果是并没有提示授权,估计是授权出了问题;

还好我们的定位服务提供了回调方法:

我们可以看到,授权的状态是被拒绝的,那就一定是授权出了问题,再次浏览代码,并没有发现问题,仔细看了看info.plist中的配置才发现这里有问题:

这个String为什么是黑色的。。那么如何才能变成系统灰色,默认不可修改的状态呢,可以像这样:

就是加上Privacy隐私权限设置,再试下,ok了。


iOS开发中的常用权限:

在获取权限之前,可以通过一下几种方式向用户请求:

1.在用户打开APP时就向用户请求权限;
2.告知用户授权权限后能够获得好处之后,再向用户请求权限;
3.在绝对必要的情况下才向用户请求权限,例如:用户访问照片库时请求访问系统相册权限;
4.在展示系统权限的对话框前,先向用户显示自定义的对话框,若用户选择不允许,默认无操作,若用户选择允许,再展示系统对话框。

常用的几种权限包括:联网权限,相册权限,相机、麦克风权限,定位权限,推送权限,通讯录权限,日历、备忘录权限;
注意这些都需要在info.plist中配置:
添加一个属性,输入Privacy后就会出现自动提示:
麦克风权限: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 是否允许此App使用日历?
定位权限:Privacy - Location When In Use Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据
定位权限: Privacy - Location Always Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据。定位的需要这么写,防止上架被拒。

联网权限:

头文件:@import CoreTelephony

检测权限:

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;}


相册权限(iOS8之后):

头文件:@import Photos

检测权限:

PHAuthorizationStatus photoAuthorStatus = [PHPhotoLibrary authorizationStatus];switch (photoAuthorStatus) {  case PHAuthorizationStatusAuthorized:      NSLog(@"Authorized");      break;  case PHAuthorizationStatusDenied:      NSLog(@"Denied");      break;  case PHAuthorizationStatusNotDetermined:      NSLog(@"not Determined");      break;  case PHAuthorizationStatusRestricted:      NSLog(@"Restricted");      break;  default:      break;}


获取权限:

[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {  if (status == PHAuthorizationStatusAuthorized) {      NSLog(@"Authorized");  }else{      NSLog(@"Denied or Restricted");  }  }];


相机和麦克风权限:

头文件:@import AVFoundation

检测权限:

AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];//相机权限AVAuthorizationStatus AVstatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];//麦克风权限switch (AVstatus) {  case AVAuthorizationStatusAuthorized:      NSLog(@"Authorized");      break;  case AVAuthorizationStatusDenied:      NSLog(@"Denied");      break;  case AVAuthorizationStatusNotDetermined:      NSLog(@"not Determined");      break;  case AVAuthorizationStatusRestricted:      NSLog(@"Restricted");      break;  default:      break;}


获取权限:

[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {//相机权限 if (granted) { NSLog(@"Authorized"); }else{ NSLog(@"Denied or Restricted"); } }]; [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {//麦克风权限  if (granted) {      NSLog(@"Authorized");  }else{      NSLog(@"Denied or Restricted");  }}];

定位权限:

头文件:@import CoreLocation

检测权限:

 BOOL isLocation = [CLLocationManager locationServicesEnabled];if (!isLocation) {  NSLog(@"not turn on the location");}CLAuthorizationStatus CLstatus = [CLLocationManager authorizationStatus];switch (CLstatus) {  case kCLAuthorizationStatusAuthorizedAlways:      NSLog(@"Always Authorized");      break;  case kCLAuthorizationStatusAuthorizedWhenInUse:      NSLog(@"AuthorizedWhenInUse");      break;  case kCLAuthorizationStatusDenied:      NSLog(@"Denied");      break;  case kCLAuthorizationStatusNotDetermined:      NSLog(@"not Determined");      break;  case kCLAuthorizationStatusRestricted:      NSLog(@"Restricted");      break;  default:      break;}


获取权限:

CLLocationManager *manager = [[CLLocationManager alloc] init];[manager requestAlwaysAuthorization];//一直获取定位信息[manager requestWhenInUseAuthorization];//使用的时候获取定位信息


代理方法中查看权限变化:

- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{ switch (status) {  case kCLAuthorizationStatusAuthorizedAlways:      NSLog(@"Always Authorized");      break;  case kCLAuthorizationStatusAuthorizedWhenInUse:      NSLog(@"AuthorizedWhenInUse");      break;  case kCLAuthorizationStatusDenied:      NSLog(@"Denied");      break;  case kCLAuthorizationStatusNotDetermined:      NSLog(@"not Determined");      break;  case kCLAuthorizationStatusRestricted:      NSLog(@"Restricted");      break;  default:      break;  }}

推送权限:

检测权限:

 UIUserNotificationSettings *settings = [[UIApplication sharedApplication] currentUserNotificationSettings];switch (settings.types) {  case UIUserNotificationTypeNone:      NSLog(@"None");      break;  case UIUserNotificationTypeAlert:      NSLog(@"Alert Notification");      break;  case UIUserNotificationTypeBadge:      NSLog(@"Badge Notification");      break;  case UIUserNotificationTypeSound:      NSLog(@"sound Notification'");      break;  default:      break;}


获取权限:

UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge categories:nil];[[UIApplication sharedApplication] registerUserNotificationSettings:setting];


通讯录权限(ios9之前):

头文件:@import AddressBook

检测权限:

 ABAuthorizationStatus ABstatus = ABAddressBookGetAuthorizationStatus();switch (ABstatus) {  case kABAuthorizationStatusAuthorized:      NSLog(@"Authorized");      break;  case kABAuthorizationStatusDenied:      NSLog(@"Denied'");      break;  case kABAuthorizationStatusNotDetermined:      NSLog(@"not Determined");      break;  case kABAuthorizationStatusRestricted:      NSLog(@"Restricted");      break;  default:      break;}


获取权限:

ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {  if (granted) {      NSLog(@"Authorized");      CFRelease(addressBook);  }else{      NSLog(@"Denied or Restricted");  }});


通讯录权限(ios9之后):

头文件:@import Contacts

检测权限:

CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];  switch (status) {        case CNAuthorizationStatusAuthorized:        {            NSLog(@"Authorized:");        }            break;        case CNAuthorizationStatusDenied:{            NSLog(@"Denied");        }            break;        case CNAuthorizationStatusRestricted:{            NSLog(@"Restricted");        }            break;        case CNAuthorizationStatusNotDetermined:{             NSLog(@"NotDetermined");        }            break;       }


获取权限:

CNContactStore *contactStore = [[CNContactStore alloc] init];    [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {        if (granted) {           NSLog(@"Authorized");        }else{           NSLog(@"Denied or Restricted");        }    }];


日历、备忘录权限:

 typedef NS_ENUM(NSUInteger, EKEntityType) {  EKEntityTypeEvent,//日历  EKEntityTypeReminder //备忘 };


检测权限:

EKAuthorizationStatus EKstatus = [EKEventStore  authorizationStatusForEntityType:EKEntityTypeEvent];switch (EKstatus) {  case EKAuthorizationStatusAuthorized:      NSLog(@"Authorized");      break;  case EKAuthorizationStatusDenied:      NSLog(@"Denied'");      break;  case EKAuthorizationStatusNotDetermined:      NSLog(@"not Determined");      break;  case EKAuthorizationStatusRestricted:      NSLog(@"Restricted");      break;  default:      break;}


获取权限:

EKEventStore *store = [[EKEventStore alloc]init];[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {  if (granted) {      NSLog(@"Authorized");  }else{      NSLog(@"Denied or Restricted");  }}];


iOS 8.0之后,将这些设置都整合在一起,并且可以开启或关闭相应的权限。所有的权限都可以通过下面的方法打开:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:
UIApplicationOpenSettingsURLString]];


参考文章:http://www.jianshu.com/p/27e57922232b


2 0
原创粉丝点击