Как я могу изящно обработать отказ в авторизации в AVCaptureDeviceInput.init? - PullRequest
1 голос
/ 24 апреля 2020

Документация для AVCaptureDeviceInput.init(device:) документирует его параметры как:

device Устройство, с которого можно захватить ввод.

outError Если ошибка происходит во время инициализации, при возврате содержит объект NSError, описывающий проблему.

Этот выходной параметр outError в Swift представлен как брошенный Error. Я могу уловить и отобразить это следующим образом:

do {
    let deviceInput = try AVCaptureDeviceInput(device: device)
    // ...
}
catch {
    print("Error: \(error)")
}

Существует один конкретный случай c, который я хочу изящно обработать: когда пользователь отказал в разрешении приложению использовать камеру. В этом случае я получаю следующий вывод:

Error: Error Domain=AVFoundationErrorDomain Code=-11852 "Cannot use FaceTime HD Camera (Built-in)" UserInfo={NSLocalizedFailureReason=This app is not authorized to use FaceTime HD Camera (Built-in)., AVErrorDeviceKey=<AVCaptureDALDevice: 0x100520a60 [FaceTime HD Camera (Built-in)][0x8020000005ac8514]>, NSLocalizedDescription=Cannot use FaceTime HD Camera (Built-in)}

Мне нужно отличить guish этот тип ошибки от других непредвиденных ошибок, например:

do {
    let deviceInput = try AVCaptureDeviceInput(device: device)
    // ...
}
catch AVError.Code.applicationIsNotAuthorizedToUseDevice {
  // Expected error, handle gracefully
  errorMessageBox(errorText: "You have denied authorization to access your camera. Fix this in System Preferences > Security & Privacy.")
}
catch {
  // Unexpected errors
  errorMessageBox("Error: \(error)")
}

This является псевдокодом и не компилируется. Я знаю, что код ошибки -11852 равен AVError.Code.applicationIsNotAuthorizedToUseDevice. Однако я не знаю, как получить код ошибки из непрозрачного объекта error, чтобы проверить его.

Каков конкретный тип c ошибки, выдаваемой AVCaptureDeviceInput.init(device:)? Как мне извлечь AVError.Code из него, чтобы обработать эту указанную c ошибку?

1 Ответ

1 голос
/ 24 апреля 2020

Есть два возможных подхода. Одним из них является проверка, прежде чем вы даже попытаетесь, например,

if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
    offerToOpenSettings()
    return
}

Другой подход заключается в catch несанкционированной ошибке:

let input: AVCaptureDeviceInput
do {
    input = try AVCaptureDeviceInput(device: camera)
} catch AVError.applicationIsNotAuthorizedToUseDevice {
    offerToOpenSettings()
    return
} catch {
    print("some other error", error)
    return
}

Обратите внимание, что ловит AVError.applicationIsNotAuthorizedToUseDevice, а не AVError.Code.applicationIsNotAuthorizedToUseDevice.

Если, например, это было приложение iOS, вы могли бы предложить функцию перенаправления пользователя в приложение настроек:

func offerToOpenSettings() {
    guard
        let settings = URL(string: UIApplication.openSettingsURLString),
        UIApplication.shared.canOpenURL(settings)
    else { return }

    let alert = UIAlertController(title: nil, message: "Would you like to open Settings to enable permission to use the camera?", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Settings", style: .default) { _ in
        UIApplication.shared.open(settings)
    })
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))

    present(alert, animated: true)
}

Примечание, поскольку это потенциально представляет предупреждение, вы не хотите запускать его в viewDidLoad (что слишком рано в процессе), а скорее viewDidAppear.

Или, в macOS, что-то вроде:

func offerToOpenSettings() {
    let preferences = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Camera")!
    let alert = NSAlert()
    alert.messageText = #"The camera is disabled. Please go to the “Camera” section in Security System Preferences, and enable this app."#
    alert.addButton(withTitle: "System Preferences")
    alert.addButton(withTitle: "Cancel")
    if alert.runModal() == .alertFirstButtonReturn {
        NSWorkspace.shared.open(preferences)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...