Solución:
Comprobar el AVAuthorizationStatus
y manejar los casos correctamente.
NSString *mediaType = AVMediaTypeVideo;
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:mediaType];
if(authStatus == AVAuthorizationStatusAuthorized) {
// do your logic
} else if(authStatus == AVAuthorizationStatusDenied){
// denied
} else if(authStatus == AVAuthorizationStatusRestricted){
// restricted, normally won't happen
} else if(authStatus == AVAuthorizationStatusNotDetermined){
// not determined?!
[AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) {
if(granted){
NSLog(@"Granted access to %@", mediaType);
} else {
NSLog(@"Not granted access to %@", mediaType);
}
}];
} else {
// impossible, unknown authorization status
}
Swift 4 y más reciente
Asegurate que:
import AVFoundation
El siguiente código comprueba todos los posibles estados de permiso:
let cameraMediaType = AVMediaType.video
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: cameraMediaType)
switch cameraAuthorizationStatus {
case .denied: break
case .authorized: break
case .restricted: break
case .notDetermined:
// Prompting user for the permission to use the camera.
AVCaptureDevice.requestAccess(for: cameraMediaType) { granted in
if granted {
print("Granted access to (cameraMediaType)")
} else {
print("Denied access to (cameraMediaType)")
}
}
}
Desde iOS 10 necesitas especificar
NSCameraUsageDescription
Ingrese su Info.plist para poder solicitar acceso a la cámara; de lo contrario, su aplicación se bloqueará en tiempo de ejecución. Consulte API que requieren descripciones de uso.
Como nota al margen interesante, ¿sabías que iOS mata la aplicación si se está ejecutando mientras cambias los permisos de la cámara en Configuración?
Desde el foro de desarrolladores de Apple:
El sistema realmente mata su aplicación si el usuario alterna el acceso de su aplicación a cámara en la configuración de. Lo mismo se aplica a cualquier clase de datos protegida en la sección Configuración → Privacidad.
Solución rápida
extension AVCaptureDevice {
enum AuthorizationStatus {
case justDenied
case alreadyDenied
case restricted
case justAuthorized
case alreadyAuthorized
case unknown
}
class func authorizeVideo(completion: ((AuthorizationStatus) -> Void)?) {
AVCaptureDevice.authorize(mediaType: AVMediaType.video, completion: completion)
}
class func authorizeAudio(completion: ((AuthorizationStatus) -> Void)?) {
AVCaptureDevice.authorize(mediaType: AVMediaType.audio, completion: completion)
}
private class func authorize(mediaType: AVMediaType, completion: ((AuthorizationStatus) -> Void)?) {
let status = AVCaptureDevice.authorizationStatus(for: mediaType)
switch status {
case .authorized:
completion?(.alreadyAuthorized)
case .denied:
completion?(.alreadyDenied)
case .restricted:
completion?(.restricted)
case .notDetermined:
AVCaptureDevice.requestAccess(for: mediaType, completionHandler: { (granted) in
DispatchQueue.main.async {
if granted {
completion?(.justAuthorized)
} else {
completion?(.justDenied)
}
}
})
@unknown default:
completion?(.unknown)
}
}
}
Y luego para usarlo lo haces
AVCaptureDevice.authorizeVideo(completion: { (status) in
//Your work here
})