banchichen / TZImagePickerController

一个支持多选、选原图和视频的图片选择器,同时有预览、裁剪功能,支持iOS6+。 A clone of UIImagePickerController, support picking multiple photos、original photo、video, also allow preview photo and video, support iOS6+
MIT License
8.05k stars 1.86k forks source link

建议将/// 拍照按钮点击事件 - (void)takePhoto提到点h文件 #1351

Closed 295060456 closed 4 years ago

295060456 commented 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
banchichen commented 4 years ago

没太明白,takePhoto放到.h文件的意义是? 鉴权单独列出来的目的是?

295060456 commented 4 years ago

类的目的是单一功能性原则,你把鉴权单独抽出来,我其他地方好调用。 takePhoto放在.h 说明我要在外部进行调用啊

banchichen commented 4 years ago

1、要在外部拍照的话,参考demo的【把拍照按钮放在外面】开关 2、鉴权的地方很少,都聚合在启动流程里了,都抽成单独文件反而繁杂