简单用gpt训练了个权限请求管理类,使用RxSwift返回,支持链式请求,支持多权限请求,失败权限使用error抛出
//
// PermissionManager.swift
// HoneyChat
//
// Created by hccc on 2023/3/16.
//
import Foundation
import RxSwift
import AVFoundation
import Photos
import CoreLocation
import MediaPlayer
import CoreBluetooth
import AppTrackingTransparency
enum PermissionError: Error {
/// 音频权限
case audio
/// 视频权限
case video
/// 蓝牙权限
case bluetooth
/// 定位权限
case location
/// 相册权限
case photoLibrary
/// 相机权限
case camera
/// 隐私权限跟踪授权
case tracking
}
// 枚举定义不同的权限类型
enum PermissionType {
/// 音频权限
case audio
/// 视频权限
case video
/// 蓝牙权限
case bluetooth
/// 定位权限
case location
/// 相册权限
case photoLibrary
/// 相机权限
case camera
/// 跟踪授权
case tracking
var error: PermissionError {
switch self {
case .audio:
return .audio
case .video:
return .video
case .bluetooth:
return .bluetooth
case .location:
return .location
case .photoLibrary:
return .photoLibrary
case .camera:
return .camera
case .tracking:
return .tracking
}
}
// 根据不同的权限类型获取相应的媒体类型
var avMediaType: AVMediaType? {
switch self {
case .audio:
return .audio
case .video:
return .video
case .camera:
return .video
default:
return nil
}
}
// 根据不同的权限类型获取相应的媒体类型
var mediaType: PHAssetMediaType? {
switch self {
case .photoLibrary:
return .image
default:
return nil
}
}
// 获取蓝牙权限状态
var cbPeripheralManagerAuthorizationStatus: CBPeripheralManagerAuthorizationStatus? {
switch self {
case .bluetooth:
return CBPeripheralManager.authorizationStatus()
default:
return nil
}
}
}
class PermissionManager {
private static let locationManager = CLLocationManager() // 定义 CLLocationManager 实例
// MARK: 请求多个权限
static func requestPermissions( _ types: PermissionType...) -> Observable<Void> {
guard types.count > 0 else {
return .empty()
}
var obserable: Observable<Void> = .just(())
for type in types {
obserable = obserable.flatMap { _ -> Observable<Void> in
return PermissionManager
.requestPermission(for: type)
.map({ grant in
if grant {
return ()
} else {
// 错误的权限直接丢出响应的错误
throw type.error
}
})
}
}
return obserable.observe(on: MainScheduler.asyncInstance)
}
// MARK: 请求系统权限静态方法并返回 Observable 对象
static func requestPermission(for permissionType: PermissionType) -> Observable<Bool> {
switch permissionType {
case .audio, .video, .camera:
return requestMediaPermission(for: permissionType) // 请求音视频、相机权限
case .location:
return requestLocationPermission() // 请求定位权限
case .photoLibrary:
return requestPhotoLibraryPermission() // 请求相册权限
case .bluetooth:
return requestBluetoothPermission() // 请求蓝牙权限
case .tracking:
return requestTrackingAuthorization() // 请求隐私权限
}
}
// MARK: 请求音视频、相机权限
private static func requestMediaPermission(for permissionType: PermissionType) -> Observable<Bool> {
guard let mediaType = permissionType.avMediaType else {
return .empty()
}
return Observable.create { observer in
let status = AVCaptureDevice.authorizationStatus(for: mediaType)
switch status {
case .authorized:
observer.onNext(true)
observer.onCompleted()
case .notDetermined:
AVCaptureDevice.requestAccess(for: mediaType) { granted in
observer.onNext(granted)
observer.onCompleted()
}
default:
observer.onNext(false)
observer.onCompleted()
}
return Disposables.create()
}
}
// MARK: 请求定位权限
private static func requestLocationPermission() -> Observable<Bool> {
return Observable.create { observer in
let status = CLLocationManager.authorizationStatus()
switch status {
case .authorizedWhenInUse, .authorizedAlways:
observer.onNext(true)
observer.onCompleted()
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
observer.onNext(false)
default:
observer.onNext(false)
observer.onCompleted()
}
return Disposables.create()
}
}
// MARK: 请求相册权限
private static func requestPhotoLibraryPermission() -> Observable<Bool> {
return Observable.create { observer in
let status = PHPhotoLibrary.authorizationStatus()
switch status {
case .authorized:
observer.onNext(true)
observer.onCompleted()
case .notDetermined:
PHPhotoLibrary.requestAuthorization { status in
observer.onNext(status == .authorized)
observer.onCompleted()
}
default:
observer.onNext(false)
observer.onCompleted()
}
return Disposables.create()
}
}
// MARK: 请求蓝牙权限
private static func requestBluetoothPermission() -> Observable<Bool> {
guard let status = PermissionType.bluetooth.cbPeripheralManagerAuthorizationStatus else {
return .just(false)
}
switch status {
case .authorized, .notDetermined:
return .just(true)
default:
return .just(false)
}
}
// MARK: 请求隐私权限
private static func requestTrackingAuthorization() -> Observable<Bool> {
if #available(iOS 14, *) {
return Observable<Bool>.create { obs in
ATTrackingManager.requestTrackingAuthorization(completionHandler: { status in
switch status {
case .authorized:
// 用户已授权追踪权限
obs.onNext(true)
obs.onCompleted()
case .denied:
// 用户拒绝了追踪权限
obs.onNext(false)
obs.onCompleted()
case .notDetermined:
// 还没有询问用户是否授权追踪
obs.onNext(false)
obs.onCompleted()
case .restricted:
// 应用程序无法请求追踪权限,例如由于家长控制等限制
obs.onNext(false)
obs.onCompleted()
@unknown default:
obs.onNext(false)
obs.onCompleted()
}
})
return Disposables.create()
}
} else {
return .just(true)
// 如果设备运行的是较早的 iOS 版本,则不需要请求追踪权限。
}
}
}