iOS Swift如何实现点击按钮后依次请求相机与相册访问权限
问题根因
你当前代码的两个权限请求是并行执行的,没有顺序依赖。PHPhotoLibrary.requestAuthorization是异步回调,相机权限请求不会等相册权限的回调和后续UI操作完成就会触发,才会出现弹窗叠加的问题。
前置配置要求
请先在项目的Info.plist中添加如下权限描述,否则请求权限会直接崩溃:
NSPhotoLibraryUsageDescription:相册访问用途说明NSCameraUsageDescription:相机访问用途说明
修复后的实现代码
import Photos import AVFoundation func checkPermissions() { // 先判断相册是否可用,优先请求相册权限 guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else { // 相册不可用,直接请求相机权限 requestCameraPermissionIfNeeded() return } PHPhotoLibrary.requestAuthorization(for: .readWrite) { [weak self] status in guard let self = self else { return } DispatchQueue.main.async { switch status { case .notDetermined, .restricted, .denied: print("相册权限未授权") self.showAlertToOpenSettings(type: 1) // 相册权限请求完成后再请求相机权限 self.requestCameraPermissionIfNeeded() case .authorized: print("相册权限已授权") self.openPhotoPicker() // 相册操作触发后再请求相机权限 self.requestCameraPermissionIfNeeded() case .limited: print("相册有限权限") self.showLimitedLibraryAlert() // 有限权限提示展示后再请求相机权限 self.requestCameraPermissionIfNeeded() @unknown default: fatalError() } } } } // 封装独立的相机权限请求方法 private func requestCameraPermissionIfNeeded() { guard UIImagePickerController.isSourceTypeAvailable(.camera) else { return } AVCaptureDevice.requestAccess(for: .video) { [weak self] response in guard let self = self else { return } if !response { DispatchQueue.main.async { self.showAlertToOpenSettings(type: 2) } } } }
核心修改说明
- 把相机权限请求封装为独立方法,仅在相册权限的所有回调逻辑(包括UI操作)执行完成后再调用,保证权限请求的顺序执行
- 新增
[weak self]避免循环引用,所有UI相关操作统一调度到主队列执行,符合UIKit的线程要求 - 新增相册不可用的兜底逻辑,兼容没有相册权限的设备场景
可选优化建议
- 如果你的业务不需要用户进入页面就同时拥有两个权限,可以把相机权限请求放到用户实际点击拍照功能的时候再触发,减少首次使用时的权限弹窗数量,降低用户抵触
- 统一权限被拒的弹窗逻辑,避免重复展示相同类型的提示
内容的提问来源于stack exchange,提问作者Diksha Rattan
相关产品推荐
相关产品推荐

