1. App权限管理

GWUtilCore组件增加PrivacyManager,统一App内权限获取。

1.1. 自定义隐私类型

目前App只涉及3种权限,定义如下:

/*
 * 隐私权限类型
 1. 在Info.plist文件中配置应用所需权限;
 2. 在项目的Targets->Capabilities中开启相应开关,目前Siri、Health、NFC、HomeKit需要开启;
 3. 引入相关库;
 4. 使用代码获取对应的隐私权限。
 */
public enum PrivacyType {
    // 相机 Authorized Denied Unsupported Unkonw
    case camera
    // 相册 NotDetermined Authorized Denied Restricted Unkonw
    case photos
    // 定位 NotDetermined Unkonw Denied Authorized:AuthorizedAlways||AuthorizedWhenInUse
    case location

    public var title: String {
        ......
    }

    public var subTitle: String {
        ......
    }

    public static var all :[PrivacyType] {
        return [.location , .camera , .photos]
    }
}

1.2. 自定义权限类型

将权限结果统一包装为自定义的类型,定义如下:

/// 获取隐私权限结果
public enum AuthorizationStatus{
    // 未知
    case unknow
    // 授权
    case authorized
    // 拒绝
    case denied
    // 不支持
    case unsupported
    // 未决定(相册,地理位置)
    case notDetermined

    public var title: String {
        ......
    }

    public var titleColor: UIColor? {
        ......
    }
}

1.3. 隐私权限管理

PrivacyManager提供两个请求隐私权限的类方法,定义如下:

synRequestAccess方法为同步方法,可以同步获取指定隐私的权限。

/// 同步请求隐私权限
/// - Parameter type: 隐私权限类型
/// - Returns: 隐私权限
public static func synRequestAccess(_ type: PrivacyType) -> AuthorizationStatus {
    switch type {
    case .photos:
        return shared.requestAccessPhotos(nil)
    case .location:
        return shared.requestAccessLocation(nil)
    case .camera:
        return shared.requestAccessCamera(nil)
    }
}

asynRequestAccess方法为异步方法,通过传入completionHandle异步获取隐私的权限,如果是第一次会触发询问窗口,当用户决定后,completionHandle会将决定后的结果返回。

/// 异步请求隐私权限
/// - Parameters:
///   - type: 隐私权限类型
///   - completionHandle: 隐私权限结果代码块
public static func asynRequestAccess(_ type: PrivacyType , completionHandle: ((AuthorizationStatus) -> Void)?) {
    switch type {
    case .photos:
        _ = shared.requestAccessPhotos(completionHandle)
        break
    case .location:
        _ = shared.requestAccessLocation(completionHandle)
        break
    case .camera:
        _ = shared.requestAccessCamera(completionHandle)
        break
}

1.4. 请求权限实现

extension PrivacyManager: CLLocationManagerDelegate {

    /// 在主线程回调隐私权限结果
    /// - Parameters:
    ///   - status: 隐私权限结果
    ///   - completionHandle: 隐私权限结果代码块
    private func response(status: AuthorizationStatus, completionHandle: ((AuthorizationStatus) -> Void)?) {
        DispatchQueue.main.async {
            completionHandle?(status)
        }
    }

    // MARK: 请求相机访问权限
    func requestAccessCamera(_ completionHandle: ((AuthorizationStatus) -> Void)?) -> AuthorizationStatus {
        if UIImagePickerController.isSourceTypeAvailable(.camera) {
            let status = AVCaptureDevice.authorizationStatus(for: .video)
            if status == .notDetermined {
                if completionHandle != nil {
                    AVCaptureDevice.requestAccess(for: .video) {  [weak self] (granted) in
                        if granted{
                            self?.response(status: .authorized, completionHandle: completionHandle)
                        }
                        else {
                            self?.response(status: .denied, completionHandle: completionHandle)
                        }
                    }
                }
                return .notDetermined
            }
            else if status == .authorized{
                response(status: .authorized, completionHandle: completionHandle)
                return .authorized
            }
            else if status == .denied || status == .restricted{
                response(status: .denied, completionHandle: completionHandle)
                return .denied
            }
            else {
                response(status: .unknow, completionHandle: completionHandle)
                return .unknow
            }
        }
        else{
            response(status: .unsupported, completionHandle: completionHandle)
            return .unsupported
        }
    }

    // MARK: 请求相册权限
    func requestAccessPhotos(_ completionHandle: ((AuthorizationStatus) -> Void)?) -> AuthorizationStatus {
        let status = PHPhotoLibrary.authorizationStatus()
        if status == .notDetermined {
            if completionHandle != nil {

                PHPhotoLibrary.requestAuthorization { [weak self] (status) in
                    if status == .notDetermined{
                        self?.response(status: .notDetermined, completionHandle: completionHandle)
                    }
                    else if status == .denied || status == .restricted {
                        self?.response(status: .denied, completionHandle: completionHandle)
                    }
                    else{
                        self?.response(status: .authorized, completionHandle: completionHandle)
                    }
                }
            }
            return .notDetermined
        }
        else if status == .authorized {
            response(status: .authorized, completionHandle: completionHandle)
            return .authorized
        }
        else if status == .denied || status == .restricted {
            response(status: .denied, completionHandle: completionHandle)
            return .denied
        }
        else{
            response(status: .unknow, completionHandle: completionHandle)
            return .unknow
        }
    }

    // MARK: 请求定位权限
    func requestAccessLocation(_ completionHandle: ((AuthorizationStatus) -> Void)?) -> AuthorizationStatus {
        let status = CLLocationManager.authorizationStatus()
        let serviceEnabled = CLLocationManager.locationServicesEnabled()
        if !serviceEnabled {
            return .unsupported
        }
        else if status == .notDetermined {
            if completionHandle != nil {
                PrivacyManager.shared.locationCompletionBlock = completionHandle
                let loc = CLLocationManager()
                loc.delegate = PrivacyManager.shared
                loc.requestWhenInUseAuthorization()
                loc.startUpdatingLocation()
                PrivacyManager.shared.locationManager = loc
            }
            return .notDetermined
        }
        else if status == .denied || status == .restricted {
            response(status: .denied, completionHandle: completionHandle)
            return .denied
        }
        else if status == .authorizedAlways || status == .authorizedWhenInUse{
            response(status: .authorized, completionHandle: completionHandle)
            return .authorized
        }
        else{
            response(status: .unknow, completionHandle: completionHandle)
            return .unknow
        }
    }

    public func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        switch status {
        case .notDetermined:
            response(status: .notDetermined, completionHandle: PrivacyManager.shared.locationCompletionBlock)
            break
        case .denied, .restricted:
            response(status: .denied, completionHandle: PrivacyManager.shared.locationCompletionBlock)
            PrivacyManager.shared.locationCompletionBlock = nil
            break
        case .authorizedAlways, .authorizedWhenInUse:
            response(status: .authorized, completionHandle: PrivacyManager.shared.locationCompletionBlock)
            PrivacyManager.shared.locationCompletionBlock = nil
            break
        @unknown default:
            response(status: .unknow, completionHandle: PrivacyManager.shared.locationCompletionBlock)
            PrivacyManager.shared.locationCompletionBlock = nil
            break
        }
    }
}

results matching ""

    No results matching ""