Closed 295060456 closed 4 years ago
关于鉴权,建议你单独列出来,我在网上找了个,自己改了改,可以用这个,反正不管你用谁的建议单列出来。 下面是代码:
.h: // // ECAuthorizationTools.h // ECAuthorizationTools // // Created by EchoZuo on 2017/6/20. // Copyright © 2017年 Echo.Z. All rights reserved. // //https://github.com/EchoZuo/ECAuthorizationTools/blob/master/README.md /* Abstract:Checking and Requesting Access to Data Classes in Privacy Settings. Abstract:检查和请求访问隐私设置数据。 */ @import Foundation; @import UIKit; @import AssetsLibrary; @import Photos; @import AddressBook; @import Contacts; @import AVFoundation; @import CoreBluetooth; @import CoreLocation; @import EventKit; @import Speech; @import HealthKit; @import HomeKit; @import StoreKit; @import CoreMotion; /* Enumerate */ // Privacy classify 分类 typedef NS_ENUM(NSUInteger, ECPrivacyType){ ECPrivacyType_None = 0, ECPrivacyType_LocationServices = 1, // 定位服务 ECPrivacyType_Contacts = 2, // 通讯录 ECPrivacyType_Calendars = 3, // 日历 ECPrivacyType_Reminders = 4, // 提醒事项 ECPrivacyType_Photos = 5, // 照片 ECPrivacyType_BluetoothSharing = 6, // 蓝牙共享 ECPrivacyType_Microphone = 7, // 麦克风 ECPrivacyType_SpeechRecognition = 8, // 语音识别 >= iOS10 ECPrivacyType_Camera = 9, // 相机 ECPrivacyType_Health = 10, // 健康 >= iOS8.0 ECPrivacyType_HomeKit = 11, // 家庭 >= iOS8.0 ECPrivacyType_MediaAndAppleMusic = 12, // 媒体与Apple Music >= iOS9.3 ECPrivacyType_MotionAndFitness = 13, // 运动与健身 }; // ECAuthorizationStatus 权限状态,参考PHAuthorizationStatus等 typedef NS_ENUM(NSUInteger, ECAuthorizationStatus){ ECAuthorizationStatus_NotDetermined = 0, // 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权 ECAuthorizationStatus_Authorized = 1, // 已授权 ECAuthorizationStatus_Denied = 2, // 拒绝 ECAuthorizationStatus_Restricted = 3, // 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制 ECAuthorizationStatus_NotSupport = 4, // 硬件等不支持 }; // ECLocationAuthorizationStatus 定位权限状态,参考CLAuthorizationStatus typedef NS_ENUM(NSUInteger, ECLocationAuthorizationStatus){ ECLocationAuthorizationStatus_NotDetermined = 0, // 用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权 ECLocationAuthorizationStatus_Authorized = 1, // 一直允许获取定位 ps:< iOS8用 ECLocationAuthorizationStatus_Denied = 2, // 拒绝 ECLocationAuthorizationStatus_Restricted = 3, // 应用没有相关权限,且当前用户无法改变这个权限,比如:家长控制 ECLocationAuthorizationStatus_NotSupport = 4, // 硬件等不支持 ECLocationAuthorizationStatus_AuthorizedAlways = 5, // 一直允许获取定位 ECLocationAuthorizationStatus_AuthorizedWhenInUse = 6, // 在使用时允许获取定位 }; // ECCBManagerState 蓝牙状态,参考 CBManagerState typedef NS_ENUM(NSUInteger, ECCBManagerStatus){ ECCBManagerStatusUnknown = 0, // 未知状态 ECCBManagerStatusResetting = 1, // 正在重置,与系统服务暂时丢失 ECCBManagerStatusUnsupported = 2, // 不支持蓝牙 ECCBManagerStatusUnauthorized = 3, // 未授权 ECCBManagerStatusPoweredOff = 4, // 关闭 ECCBManagerStatusPoweredOn = 5, // 开启并可用 }; /* 定义权限状态回调block */ typedef id(^AccessForTypeResultBlock)(ECAuthorizationStatus status, ECPrivacyType type); typedef void(^AccessForLocationResultBlock)(ECLocationAuthorizationStatus status); typedef void(^AccessForBluetoothResultBlock)(ECCBManagerStatus status); typedef void(^AccessForHomeResultBlock)(BOOL isHaveHomeAccess); @interface ECAuthorizationTools : NSObject @property(nonatomic,strong)CLLocationManager *locationManager; // 定位 @property(nonatomic,strong)CBCentralManager *cMgr; // 蓝牙 @property(nonatomic,strong)HKHealthStore *healthStore; // 健康 @property(nonatomic,strong)HMHomeManager *homeManager; // home @property(nonatomic,strong)CMMotionActivityManager *cmManager; // 运动 @property(nonatomic,strong)NSOperationQueue *motionActivityQueue; // 运动 #pragma mark -------------------- Public Methods -------------------- /* NS_ENUM -> NSString */ + (NSString *)stringForPrivacyType:(ECPrivacyType)privacyType; + (NSString *)stringForAuthorizationStatus:(ECAuthorizationStatus)authorizationStatus; + (NSString *)stringForLocationAuthorizationStatus:(ECLocationAuthorizationStatus)locationAuthorizationStatus; + (NSString *)stringForCBManagerStatus:(ECCBManagerStatus)CBManagerStatus; #pragma mark -------------------- Main Enter Method -------------------- /** Check and request access for * type 检查和请求对应类型的权限 @param type ECPrivacyType @param accessStatusCallBack AccessForTypeResultBlock */ + (void)checkAndRequestAccessForType:(ECPrivacyType)type accessStatus:(AccessForTypeResultBlock)accessStatusCallBack; /** Check and request access for LocationServices 检查和请求定位服务的权限 @param accessStatusCallBack accessStatus */ - (void)checkAndRequestAccessForLocationServicesWithAccessStatus:(AccessForLocationResultBlock)accessStatusCallBack; /** Check and request access for BluetoothSharing 检查和请求蓝牙共享服务的权限 @param accessStatusCallBack accessStatus */ - (void)checkAndRequestAccessForBluetoothSharingWithAccessStatus:(AccessForBluetoothResultBlock)accessStatusCallBack; /** Check and request access for Health 检查和请求健康的权限 @param accessStatusCallBack accessStatus */ - (void)checkAndRequestAccessForHealthWtihAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack; /** Check And Request Access For Home Tip:访问家庭权限是需要回调指定的的HMHomeManagerDelegate协议,并且回调之后的后续逻辑处理比较麻烦,建议使用者可以直接调用系统的获取权限方法。在回调协议中做处理。这里做出简单Demo以方便参考。注意:HMError.h类 @param accessForHomeCallBack AccessForHomeResultBlock */ - (void)checkAndRequestAccessForHome:(AccessForHomeResultBlock)accessForHomeCallBack; /** Check And Request Access For Motion And Fitness 同访问Home一样,运动与健身这里也只给出简单demo方便参考,可以直接copy代码到自己的项目中直接用 */ - (void)checkAndRequestAccessForMotionAndFitness; @end .m: // // ECAuthorizationTools.m // ECAuthorizationTools // // Created by EchoZuo on 2017/6/20. // Copyright © 2017年 Echo.Z. All rights reserved. // #import "ECAuthorizationTools.h" API_AVAILABLE(ios(10.0)) @interface ECAuthorizationTools () < CLLocationManagerDelegate ,CBCentralManagerDelegate ,HMHomeManagerDelegate ,UINavigationControllerDelegate > @property(nonatomic,copy)void(^kCLCallBackBlock)(CLAuthorizationStatus state); @property(nonatomic,copy)void(^CBManagerStateCallBackBlock)(CBManagerState state); @property(nonatomic,copy)void(^HomeAccessCallBackBlock)(BOOL isHaveAccess); @end @implementation ECAuthorizationTools #pragma mark - checkAndRequestAccessForType + (void)checkAndRequestAccessForType:(ECPrivacyType)type accessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if (type == ECPrivacyType_LocationServices) { // 定位服务 // [self checkAndRequestAccessForLocationServicesWithAccessStatus:accessStatusCallBack]; }else if (type == ECPrivacyType_Contacts) { // 联系人 [self checkAndRequestAccessForContactsWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_Calendars) { // 日历 [self checkAndRequestAccessForCalendarsWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_Reminders) { // 提醒事项 [self checkAndRequestAccessForRemindersWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_Photos) { // 照片 [self checkAndRequestAccessForPhotosWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_BluetoothSharing) { // 蓝牙 // [self checkAndRequestAccessForBluetoothSharingWithAccessStatus:accessStatusCallBack]; }else if (type == ECPrivacyType_Microphone) { // 麦克风 [self checkAndRequestAccessForMicrophoneWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_SpeechRecognition) { // 语音识别 [self checkAndRequestAccessForSpeechRecognitionWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_Camera) { // 相机 [self checkAndRequestAccessForCameraWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_Health) { // 健康 // [self checkAndRequestAccessForHealthWithAccessStatus:accessStatusCallBack]; }else if (type == ECPrivacyType_HomeKit) { // home // [self checkAndRequestAccessForHomeWithAccessStatus:accessStatusCallBack]; }else if (type == ECPrivacyType_MediaAndAppleMusic) { // Apple Music [self checkAndRequestAccessForAppleMusicWithAccessStatus:^id(ECAuthorizationStatus status, ECPrivacyType type) { accessStatusCallBack(status,type); return nil; }]; }else if (type == ECPrivacyType_MotionAndFitness) { // Motion // [self checkAndRequestAccessForMotionAndFitnessWtihAccessStatus:accessStatusCallBack]; }else{ // ECPrivacyType_None } } #pragma mark -------------------- LocationServices -------------------- - (void)checkAndRequestAccessForLocationServicesWithAccessStatus:(AccessForLocationResultBlock)accessStatusCallBack{ BOOL isLocationServicesEnabled = [CLLocationManager locationServicesEnabled]; if (!isLocationServicesEnabled) { NSLog(@"定位服务不可用,例如定位没有打开..."); [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_NotSupport type:ECPrivacyType_LocationServices]; }else{ CLAuthorizationStatus status = [CLLocationManager authorizationStatus]; if (status == kCLAuthorizationStatusNotDetermined) { // [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack // accessStatus:ECLocationAuthorizationStatus_NotDetermined // type:ECPrivacyType_LocationServices]; // 两种定位模式:[self.locationManager requestAlwaysAuthorization]; [self.locationManager requestWhenInUseAuthorization]; [self setKCLCallBackBlock:^(CLAuthorizationStatus state){ if (status == kCLAuthorizationStatusNotDetermined) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_NotDetermined type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusRestricted) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_Restricted type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusDenied) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_Restricted type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusAuthorizedAlways) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_AuthorizedAlways type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusAuthorizedWhenInUse) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_AuthorizedWhenInUse type:ECPrivacyType_LocationServices]; }else{ // kCLAuthorizationStatusAuthorized < ios8 [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_Authorized type:ECPrivacyType_LocationServices]; } }]; }else if (status == kCLAuthorizationStatusRestricted) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_Restricted type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusDenied) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_Restricted type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusAuthorizedAlways) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_AuthorizedAlways type:ECPrivacyType_LocationServices]; }else if (status == kCLAuthorizationStatusAuthorizedWhenInUse) { [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_AuthorizedWhenInUse type:ECPrivacyType_LocationServices]; }else{ // kCLAuthorizationStatusAuthorized < ios8 [ECAuthorizationTools executeCallBackForForLocationServices:accessStatusCallBack accessStatus:ECLocationAuthorizationStatus_Authorized type:ECPrivacyType_LocationServices]; } } } #pragma mark - CLLocationManagerDelegate - (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status{ if (self.kCLCallBackBlock) { self.kCLCallBackBlock(status); } } #pragma mark -------------------- Contacts -------------------- + (void)checkAndRequestAccessForContactsWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if (@available(iOS 9.0, *)) { CNContactStore *contactStore = CNContactStore.new; CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts]; if (status == CNAuthorizationStatusNotDetermined) { if (!contactStore) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Contacts]; } [contactStore requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) { if (error) { NSLog(@"error:%@",error); [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Contacts]; }else{ if (granted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Contacts]; }else{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Contacts]; } } }]; }else if (status == CNAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Contacts]; }else if (status == CNAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Contacts]; }else{ // CNAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Contacts]; } }else{} } #pragma mark -------------------- Calendars -------------------- + (void)checkAndRequestAccessForCalendarsWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]; if (status == EKAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Calendars]; EKEventStore *store = EKEventStore.new; if (!store) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Calendars]; }else{ @weakify(self) [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) { @strongify(self) if (error) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Calendars]; NSLog(@"erro:%@",error); } if (granted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Calendars]; }else{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Calendars]; } }]; } } else if (status == EKAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Calendars]; } else if (status == EKAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Calendars]; } else { // EKAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Calendars]; } } #pragma mark -------------------- Reminders -------------------- + (void)checkAndRequestAccessForRemindersWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder]; if (status == EKAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Reminders]; EKEventStore *store = EKEventStore.new; if (!store) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Reminders]; }else{ @weakify(self) [store requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError * _Nullable error) { @strongify(self) if (error) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Reminders]; NSLog(@"erro:%@",error); } if (granted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Reminders]; }else{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Reminders]; } }]; } } else if (status == EKAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Reminders]; } else if (status == EKAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Reminders]; } else { // EKAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Reminders]; } } #pragma mark -------------------- Photos -------------------- + (void)checkAndRequestAccessForPhotosWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; if (status == PHAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Photos]; @weakify(self) [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { @strongify(self) if (status == PHAuthorizationStatusNotDetermined) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Photos]; } else if (status == PHAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Photos]; } else if (status == PHAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Photos]; } else { // PHAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Photos]; } }]; } else if (status == PHAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Photos]; } else if (status == PHAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Photos]; } else { // PHAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Photos]; } } else { NSLog(@"相册不可用!"); [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Photos]; } } #pragma mark -------------------- BluetoothSharing -------------------- - (void)checkAndRequestAccessForBluetoothSharingWithAccessStatus:(AccessForBluetoothResultBlock)accessStatusCallBack{ self.cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil]; if (@available(iOS 10.0, *)) { [self setCBManagerStateCallBackBlock:^(CBManagerState status){ if (status == CBManagerStateResetting) { [ECAuthorizationTools executeCallBackForForBluetoothSharing:accessStatusCallBack accessStatus:ECCBManagerStatusResetting type:ECPrivacyType_BluetoothSharing]; } else if (status == CBManagerStateUnsupported) { [ECAuthorizationTools executeCallBackForForBluetoothSharing:accessStatusCallBack accessStatus:ECCBManagerStatusUnsupported type:ECPrivacyType_BluetoothSharing]; } else if (status == CBManagerStateUnauthorized) { [ECAuthorizationTools executeCallBackForForBluetoothSharing:accessStatusCallBack accessStatus:ECCBManagerStatusUnauthorized type:ECPrivacyType_BluetoothSharing]; } else if (status == CBManagerStatePoweredOff) { [ECAuthorizationTools executeCallBackForForBluetoothSharing:accessStatusCallBack accessStatus:ECCBManagerStatusPoweredOff type:ECPrivacyType_BluetoothSharing]; } else if (status == CBManagerStatePoweredOn) { [ECAuthorizationTools executeCallBackForForBluetoothSharing:accessStatusCallBack accessStatus:ECCBManagerStatusPoweredOn type:ECPrivacyType_BluetoothSharing]; } else { // CBManagerStateUnknown [ECAuthorizationTools executeCallBackForForBluetoothSharing:accessStatusCallBack accessStatus:ECCBManagerStatusUnknown type:ECPrivacyType_BluetoothSharing]; } }]; } else { // Fallback on earlier versions } } #pragma mark - CBCentralManagerDelegate - (void)centralManagerDidUpdateState:(CBCentralManager *)central{ if (self.CBManagerStateCallBackBlock) { self.CBManagerStateCallBackBlock(central.state); } } #pragma mark -------------------- Microphone -------------------- + (void)checkAndRequestAccessForMicrophoneWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]; if (status == AVAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Microphone]; @weakify(self) [[AVAudioSession sharedInstance] requestRecordPermission:^(BOOL granted) { @strongify(self) if (granted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Microphone]; }else{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Microphone]; } }]; } else if (status == AVAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Microphone]; } else if (status == AVAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Microphone]; } else { // AVAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Microphone]; } } #pragma mark -------------------- SpeechRecognition -------------------- + (void)checkAndRequestAccessForSpeechRecognitionWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if (@available(iOS 10.0, *)) { SFSpeechRecognizerAuthorizationStatus status = [SFSpeechRecognizer authorizationStatus]; if (status == SFSpeechRecognizerAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_SpeechRecognition]; @weakify(self) [SFSpeechRecognizer requestAuthorization:^(SFSpeechRecognizerAuthorizationStatus status) { @strongify(self) if (status == SFSpeechRecognizerAuthorizationStatusNotDetermined) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_SpeechRecognition]; } else if (status == SFSpeechRecognizerAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_SpeechRecognition]; } else if (status == SFSpeechRecognizerAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_SpeechRecognition]; } else { // SFSpeechRecognizerAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_SpeechRecognition]; } }]; } else if (status == SFSpeechRecognizerAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_SpeechRecognition]; } else if (status == SFSpeechRecognizerAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_SpeechRecognition]; } else { // SFSpeechRecognizerAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_SpeechRecognition]; } } else { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_SpeechRecognition]; } } #pragma mark -------------------- Camera -------------------- + (void)checkAndRequestAccessForCameraWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]; if (status == AVAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Camera]; @weakify(self) [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { @strongify(self) if (granted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Camera]; }else{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Camera]; } }]; } else if (status == AVAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_Camera]; } else if (status == AVAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Camera]; } else { // AVAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Camera]; } }else{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Camera]; } } #pragma mark -------------------- Health -------------------- - (void)checkAndRequestAccessForHealthWtihAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if (@available(iOS 8.0, *)) { if ([HKHealthStore isHealthDataAvailable]) { // 以心率 HKQuantityTypeIdentifierHeartRate 为例子 HKQuantityType *heartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]; HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:heartRateType]; if (status == HKAuthorizationStatusNotDetermined) { // [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Health]; NSSet *typeSet = [NSSet setWithObject:heartRateType]; [self.healthStore requestAuthorizationToShareTypes:typeSet readTypes:typeSet completion:^(BOOL success, NSError * _Nullable error) { // tips:这个block不止在用户点击允许或者不允许的时候响应,在弹出访问健康数据允许窗口后,只要界面发生变化(以及程序进入后台),都会响应该block。 // sucess 为YES代表用户响应了该界面,允许或者拒绝 if (success) { // 由于用户已经响该界面(不管是允许或者拒绝) // 并且这时候应该只会有两种状态:HKAuthorizationStatusSharingAuthorized 或者 HKAuthorizationStatusSharingDenied HKAuthorizationStatus status = [self.healthStore authorizationStatusForType:heartRateType]; if (status == HKAuthorizationStatusNotDetermined) { [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_Health]; } else if (status == HKAuthorizationStatusSharingAuthorized) { [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Health]; } else { // HKAuthorizationStatusSharingDenied [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Health]; } }else{ if (error) { NSLog(@"requestHealthAuthorization: error:%@",error); } } }]; } else if (status == HKAuthorizationStatusSharingAuthorized) { [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_Health]; } else { // HKAuthorizationStatusSharingDenied [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_Health]; } }else{ [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Health]; NSLog(@"unavailable"); // Health data is not avaliable on all device. } }else{ [ECAuthorizationTools executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_Health]; NSLog(@"iOS8以下不支持"); } } #pragma mark -------------------- HomeKit -------------------- - (void)checkAndRequestAccessForHome:(AccessForHomeResultBlock)accessForHomeCallBack{ if (@available(iOS 8.0, *)) { self.homeManager.delegate = self; [self setHomeAccessCallBackBlock:^(BOOL isHaveAccess){ if (accessForHomeCallBack) { accessForHomeCallBack(isHaveAccess); } }]; }else{ NSLog(@"The home is available on ios8 or later"); } } #pragma mark - HMHomeManagerDelegate - (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager{ if (manager.homes.count > 0) { NSLog(@"A home exists, so we have access."); if (self.HomeAccessCallBackBlock) { self.HomeAccessCallBackBlock(YES); } } else { @weakify(manager) [weak_manager addHomeWithName:@"Test Home" completionHandler:^(HMHome * _Nullable home, NSError * _Nullable error) { if (!error) { NSLog(@"We have access for home."); if (self.HomeAccessCallBackBlock) { self.HomeAccessCallBackBlock(YES); } } else { // tips:出现错误,错误类型参考 HMError.h if (error.code == HMErrorCodeHomeAccessNotAuthorized) { // User denied permission. NSLog(@"用户拒绝!!"); } else { NSLog(@"HOME_ERROR:%ld,%@",error.code, error.localizedDescription); } if (self.HomeAccessCallBackBlock) { self.HomeAccessCallBackBlock(YES); } } if (home) { [weak_manager removeHome:home completionHandler:^(NSError * _Nullable error) { // ... do something with the result of removing the home ... }]; } }]; } } #pragma mark -------------------- MediaAndAppleMusic -------------------- + (void)checkAndRequestAccessForAppleMusicWithAccessStatus:(AccessForTypeResultBlock)accessStatusCallBack{ if (@available(iOS 9.3, *)) { SKCloudServiceAuthorizationStatus status = [SKCloudServiceController authorizationStatus]; if (status == SKCloudServiceAuthorizationStatusNotDetermined) { // [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_MediaAndAppleMusic]; @weakify(self) [SKCloudServiceController requestAuthorization:^(SKCloudServiceAuthorizationStatus status) { @strongify(self) switch (status) { case SKCloudServiceAuthorizationStatusNotDetermined:{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotDetermined type:ECPrivacyType_MediaAndAppleMusic]; } break; case SKCloudServiceAuthorizationStatusRestricted:{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_MediaAndAppleMusic]; } break; case SKCloudServiceAuthorizationStatusDenied:{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_MediaAndAppleMusic]; } break; case SKCloudServiceAuthorizationStatusAuthorized:{ [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_MediaAndAppleMusic]; } break; default: break; } }]; } else if (status == SKCloudServiceAuthorizationStatusRestricted) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Restricted type:ECPrivacyType_MediaAndAppleMusic]; } else if (status == SKCloudServiceAuthorizationStatusDenied) { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Denied type:ECPrivacyType_MediaAndAppleMusic]; } else{ // SKCloudServiceAuthorizationStatusAuthorized [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_Authorized type:ECPrivacyType_MediaAndAppleMusic]; } } else { [self executeCallBack:accessStatusCallBack accessStatus:ECAuthorizationStatus_NotSupport type:ECPrivacyType_MediaAndAppleMusic]; NSLog(@"AppleMusic只支持iOS9.3+"); } } #pragma mark -------------------- MotionAndFitness -------------------- - (void)checkAndRequestAccessForMotionAndFitness{ @weakify(self) [self.cmManager startActivityUpdatesToQueue:self.motionActivityQueue withHandler:^(CMMotionActivity *activity) { // Do something with the activity reported. @strongify(self) [self.cmManager stopActivityUpdates]; NSLog(@"We have access for MotionAndFitness."); }]; NSLog(@"We don't have permission to MotionAndFitness."); } #pragma mark -------------------- accessStatus callbacks -------------------- // all CallBack + (void)executeCallBack:(AccessForTypeResultBlock)accessStatusCallBack accessStatus:(ECAuthorizationStatus)accessStatus type:(ECPrivacyType)type{ dispatch_async(dispatch_get_main_queue(), ^{ if (accessStatusCallBack) { accessStatusCallBack(accessStatus, type); NSLog(@"\n//************************************************************//\n获取权限类型:%@\n权限状态:%@\n//************************************************************//\n",[ECAuthorizationTools stringForPrivacyType:type], [ECAuthorizationTools stringForAuthorizationStatus:accessStatus]); } }); } // Location Services CallBack + (void)executeCallBackForForLocationServices:(AccessForLocationResultBlock)accessStatusCallBack accessStatus:(ECLocationAuthorizationStatus)accessStatus type:(ECPrivacyType)type{ dispatch_async(dispatch_get_main_queue(), ^{ if (accessStatusCallBack) { accessStatusCallBack(accessStatus); NSLog(@"\n//************************************************************//\n获取权限类型:%@\n权限状态:%@\n//************************************************************//\n",[ECAuthorizationTools stringForPrivacyType:type], [ECAuthorizationTools stringForLocationAuthorizationStatus:accessStatus]); } }); } // Bluetooth Sharing CallBack + (void)executeCallBackForForBluetoothSharing:(AccessForBluetoothResultBlock)accessStatusCallBack accessStatus:(ECCBManagerStatus)accessStatus type:(ECPrivacyType)type{ dispatch_async(dispatch_get_main_queue(), ^{ if (accessStatusCallBack) { accessStatusCallBack(accessStatus); } }); } #pragma mark -------------------- Public Methods -------------------- + (NSString *)stringForPrivacyType:(ECPrivacyType)privacyType{ if (privacyType == ECPrivacyType_LocationServices) { return @"LocationServices"; }else if (privacyType == ECPrivacyType_Contacts) { return @"Contacts"; }else if (privacyType == ECPrivacyType_Calendars) { return @"Calendars"; }else if (privacyType == ECPrivacyType_Reminders) { return @"Reminders"; }else if (privacyType == ECPrivacyType_Photos) { return @"Photos"; }else if (privacyType == ECPrivacyType_BluetoothSharing) { return @"BluetoothSharing"; }else if (privacyType == ECPrivacyType_Microphone) { return @"Microphone"; }else if (privacyType == ECPrivacyType_SpeechRecognition) { return @"SpeechRecognition"; }else if (privacyType == ECPrivacyType_Camera) { return @"Camera"; }else if (privacyType == ECPrivacyType_Health) { return @"Health"; }else if (privacyType == ECPrivacyType_HomeKit) { return @"Home"; }else if (privacyType == ECPrivacyType_MediaAndAppleMusic) { return @"Media And AppleMusic"; }else if (privacyType == ECPrivacyType_MotionAndFitness) { return @"Motion And Fitness"; }else return @""; } + (NSString *)stringForAuthorizationStatus:(ECAuthorizationStatus)authorizationStatus{ if (authorizationStatus == ECAuthorizationStatus_Authorized) { return @"Authorized"; }else if (authorizationStatus == ECAuthorizationStatus_Denied) { return @"Denied"; }else if (authorizationStatus == ECAuthorizationStatus_Restricted) { return @"Restricted"; }else if (authorizationStatus == ECAuthorizationStatus_NotSupport) { return @"NotSupport"; }else return @"NotDetermined"; } + (NSString *)stringForLocationAuthorizationStatus:(ECLocationAuthorizationStatus)locationAuthorizationStatus{ if (locationAuthorizationStatus == ECLocationAuthorizationStatus_Authorized) { return @"Location Authorized, < ios8"; }else if (locationAuthorizationStatus == ECLocationAuthorizationStatus_Denied) { return @"Location Denied"; }else if (locationAuthorizationStatus == ECLocationAuthorizationStatus_Restricted) { return @"Location Restricted"; }else if (locationAuthorizationStatus == ECLocationAuthorizationStatus_NotSupport) { return @"Location NotSupport"; }else if (locationAuthorizationStatus == ECLocationAuthorizationStatus_AuthorizedAlways) { return @"Location AuthorizedAlways"; }else if (locationAuthorizationStatus == ECLocationAuthorizationStatus_AuthorizedWhenInUse) { return @"Location AuthorizedWhenInUse"; }else return @"Location NotDetermined"; } + (NSString *)stringForCBManagerStatus:(ECCBManagerStatus)CBManagerStatus;{ if (CBManagerStatus == ECCBManagerStatusResetting) { return @"Bluetooth Resetting"; }else if (CBManagerStatus == ECCBManagerStatusUnsupported) { return @"Bluetooth Unsupported"; }else if (CBManagerStatus == ECCBManagerStatusUnauthorized) { return @"Bluetooth Unauthorized"; }else if (CBManagerStatus == ECCBManagerStatusPoweredOff) { return @"Bluetooth PoweredOff"; }else if (CBManagerStatus == ECCBManagerStatusPoweredOn) { return @"Bluetooth PoweredOn"; }else return @"Bluetooth Unknown"; } #pragma mark —— lazyLoad -(CLLocationManager *)locationManager{ if (!_locationManager) { _locationManager = CLLocationManager.new; _locationManager.delegate = self; }return _locationManager; } -(HKHealthStore *)healthStore{ if (!_healthStore) { _healthStore = HKHealthStore.new; }return _healthStore; } -(CMMotionActivityManager *)cmManager{ if (!_cmManager) { _cmManager = CMMotionActivityManager.new; }return _cmManager; } -(NSOperationQueue *)motionActivityQueue{ if (!_motionActivityQueue) { _motionActivityQueue = NSOperationQueue.new; }return _motionActivityQueue; } -(HMHomeManager *)homeManager{ if (!_homeManager) { _homeManager = HMHomeManager.new; }return _homeManager; } @end
没太明白,takePhoto放到.h文件的意义是? 鉴权单独列出来的目的是?
类的目的是单一功能性原则,你把鉴权单独抽出来,我其他地方好调用。 takePhoto放在.h 说明我要在外部进行调用啊
1、要在外部拍照的话,参考demo的【把拍照按钮放在外面】开关 2、鉴权的地方很少,都聚合在启动流程里了,都抽成单独文件反而繁杂
关于鉴权,建议你单独列出来,我在网上找了个,自己改了改,可以用这个,反正不管你用谁的建议单列出来。 下面是代码: