"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开发中的常用权限:
在获取权限之前,可以通过一下几种方式向用户请求:
2.告知用户授权权限后能够获得好处之后,再向用户请求权限;
3.在绝对必要的情况下才向用户请求权限,例如:用户访问照片库时请求访问系统相册权限;
4.在展示系统权限的对话框前,先向用户显示自定义的对话框,若用户选择不允许,默认无操作,若用户选择允许,再展示系统对话框。
常用的几种权限包括:联网权限,相册权限,相机、麦克风权限,定位权限,推送权限,通讯录权限,日历、备忘录权限;
注意这些都需要在info.plist中配置:
相机权限: 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
- "Unable to retrieve CarrierName."CTError引发的对iOS系统权限的总结
- Unable to retrieve ApplicationSettings information
- 从Unable to recognize OLE stream引发的故事
- $.ajax()引发的对Deferred的总结
- Ubuntu读取windows下的共享文件夹 Unable to mount location Failed to retrieve share list from server
- Error: Unable to retrieve volume limit information.
- Unable to retrieve AudioTrack pointer for write
- Unable to retrieve metadata for procedure
- iOS中权限的总结
- 权限系统的一点儿总结
- 由今天的错误引发对编程的思考总结
- org.apache.jasper.JasperException: Unable to load class for JSP问题引发的思考
- ADO.NET实体框架连接串引发的异常:Unable to load the specified metadata resource
- ADO.NET实体框架连接串引发的异常:Unable to load the specified metadata resource
- ORA-09925: Unable to create audit trail file引发的错误
- Android :子Activity 使用dialog 引发的BUG--android.view.WindowManager$BadTokenException: Unable to add wind
- unknown heap name引发Error detected (LME288)从而Unable to perform link问题的解决
- ORA-09925: Unable to create audit trail file引发的错误
- MySQL创建关联表的方法
- 跨浏览器确定浏览器窗口位置及窗口大小
- Spring 介绍
- Swift相关概念语法简单理解
- 断言NSAssert()和NSParameterAssert区别和用处
- "Unable to retrieve CarrierName."CTError引发的对iOS系统权限的总结
- 转:JAVA中的split方法
- NSInvocation的基本使用
- iOS-屏幕适配
- angular知识一览
- JavaScript 经典实例收集整理
- 网易视频云郭再荣:视频云服务的未来在于场景化
- 完美卸载Visual Studio2015的方法汇总
- rss订阅功能