在iOS中请求相机权限对话启动(Prime权限)

时间:2016-12-23 15:06:47

标签: ios swift permissions camera user-experience

提示用户访问相机(或其他功能)的最有效方法是什么,同时确保获得最佳体验?

访问相机时,iOS必须要求客户允许访问权限。众所周知,如果客户说“不”但随后改变主意,则无法在您的应用程序中撤销此决定。他们必须转到“设置”并按照许多步骤重新启用访问权限,即:

Settings -> Privacy -> Camera -> [Your App] -> turn switch on

1 个答案:

答案 0 :(得分:21)

权限启动是一种有效的方法,可以避免客户拒绝访问您应用的关键功能。

在iOS上,每个功能只允许应用程序触发一次默认系统权限。权限启动是指应用程序使用模仿系统权限的警报“填充”客户。

这样做的好处是,如果客户选择退出(选择取消),应用程序仍然可以在将来再次询问,直到他们说是 - 这时显示实际系统权限和客户在统计上,他们不太可能改变主意并进入负面工作流程。

此外,由于cameraSelected()执行此工作流程,如果用户拒绝,但在某个未来某点 更改其设置,应用程序将立即反映新权限而无需进一步输入(即,用户可以切换到“设置”,更改权限,然后切换回应用程序。

以下是一些实现此功能的 Swift 3 代码:

[更新:包含一个解决方案,用于打开设置的深层链接,用户可以启用相机访问权限,如果他们之前已拒绝过。)

[更新2:为Google Analytics实施添加了示例行。]

func cameraSelected() {
    // First we check if the device has a camera (otherwise will crash in Simulator - also, some iPod touch models do not have a camera).
    if let deviceHasCamera = UIImagePickerController.isSourceTypeAvailable(.camera) {
        let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
        switch authStatus {
            case .authorized:
                showCameraPicker()
            case .denied:
                alertPromptToAllowCameraAccessViaSettings()
            case .notDetermined:
                permissionPrimeCameraAccess()
            default:
                permissionPrimeCameraAccess()
        }
    } else {
        let alertController = UIAlertController(title: "Error", message: "Device has no camera", preferredStyle: .alert)
        let defaultAction = UIAlertAction(title: "OK", style: .default, handler: { (alert) in
            Analytics.track(event: .permissionsPrimeCameraNoCamera)
        })
        alertController.addAction(defaultAction)
        present(alertController, animated: true, completion: nil)
    }
}


func alertPromptToAllowCameraAccessViaSettings() {
    let alert = UIAlertController(title: "\"<Your App>\" Would Like To Access the Camera", message: "Please grant permission to use the Camera so that you can  <customer benefit>.", preferredStyle: .alert )
    alert.addAction(UIAlertAction(title: "Open Settings", style: .cancel) { alert in
        Analytics.track(event: .permissionsPrimeCameraOpenSettings)
        if let appSettingsURL = NSURL(string: UIApplicationOpenSettingsURLString) {
          UIApplication.shared.openURL(appSettingsURL)
        }
    })
    present(alert, animated: true, completion: nil)
}


func permissionPrimeCameraAccess() {
    let alert = UIAlertController( title: "\"<Your App>\" Would Like To Access the Camera", message: "<Your App> would like to access your Camera so that you can <customer benefit>.", preferredStyle: .alert )
    let allowAction = UIAlertAction(title: "Allow", style: .default, handler: { (alert) -> Void in
        Analytics.track(event: .permissionsPrimeCameraAccepted)
        if AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo).count > 0 {
            AVCaptureDevice.requestAccess(forMediaType: AVMediaTypeVideo, completionHandler: { [weak self] granted in
                DispatchQueue.main.async {
                    self?.cameraSelected() // try again
                }
            })
        }
    })
    alert.addAction(allowAction)
    let declineAction = UIAlertAction(title: "Not Now", style: .cancel) { (alert) in
        Analytics.track(event: .permissionsPrimeCameraCancelled)
    }
    alert.addAction(declineAction)
    present(alert, animated: true, completion: nil)
}


func showCameraPicker() {
    let picker = UIImagePickerController()
    picker.delegate = self
    picker.modalPresentationStyle = UIModalPresentationStyle.currentContext
    picker.allowsEditing = false
    picker.sourceType = UIImagePickerControllerSourceType.camera
    present(picker, animated: true, completion: nil)
}