Ich entwickle eine sehr einfache Video-App. Ich benutze die offizielle Steuerung: UIImagePickerController.
Hier liegt das Problem. Wenn Sie den UIImagePickerController zum ersten Mal präsentieren, werden Sie vom iOS um Erlaubnis gebeten. Der Benutzer kann auf Ja oder Nein klicken. Wenn der Benutzer auf Nein klickt, wird das Steuerelement nicht geschlossen. Wenn der Benutzer stattdessen weiter auf die Startschaltfläche klickt, werden die Zeitgeber eingeschaltet, während der Bildschirm immer schwarz ist, und der Benutzer kann die Zeitgeber nicht anhalten oder zurückkehren. Der Benutzer kann die App nur beenden. Das nächste Mal, wenn der UIImagePickerController angezeigt wird, ist der Bildschirm weiterhin schwarz und der Benutzer kann nicht zurückkehren, wenn er auf Start klickt.
Ich habe mich gefragt, ob es ein Fehler ist. Gibt es eine Möglichkeit, die Erlaubnis der Kamera zu erkennen, um zu entscheiden, ob der UIImagePickerController angezeigt werden soll oder nicht?
Überprüfen Sie die AVAuthorizationStatus
und behandeln Sie die Fälle ordnungsgemäß.
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
}
Seit iOS 10 müssen Sie in Ihrer Info.plist den NSCameraUsageDescription
Schlüssel angeben, um nach dem Zugriff auf die Kamera fragen zu können. Andernfalls stürzt Ihre App zur Laufzeit ab. Siehe APIs, die Verwendungsbeschreibungen erfordern .
Stellen Sie sicher, dass:
import AVFoundation
Der folgende Swift Code prüft auf alle möglichen Berechtigungszustände:
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)")
}
}
}
let cameraMediaType = AVMediaTypeVideo
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: 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(forMediaType: cameraMediaType) { granted in
if granted {
print("Granted access to \(cameraMediaType)")
} else {
print("Denied access to \(cameraMediaType)")
}
}
}
Wussten Sie, dass iOS die App beendet, wenn sie ausgeführt wird, während Sie die Kameraberechtigungen in den Einstellungen ändern?
Vom Apple Entwicklerforum:
Das System beendet Ihre App tatsächlich, wenn der Benutzer den Zugriff Ihrer App in den Einstellungen auf camera umschaltet. Gleiches gilt für alle geschützten Datenklassen im Bereich Einstellungen → Datenschutz.
Als Ergänzung zur Antwort von @Raptor sollte folgendes erwähnt werden. Möglicherweise wird ab iOS 10 die folgende Fehlermeldung angezeigt: This application is modifying the autolayout engine from a background thread after the engine was accessed from the main thread. This can lead to engine corruption and weird crashes.
Um dies zu beheben, stellen Sie sicher, dass Sie die Ergebnisse des Hauptthreads wie folgt verarbeiten (Swift 3):
private func showCameraPermissionPopup() {
let cameraMediaType = AVMediaTypeVideo
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: cameraMediaType)
switch cameraAuthorizationStatus {
case .denied:
NSLog("cameraAuthorizationStatus=denied")
break
case .authorized:
NSLog("cameraAuthorizationStatus=authorized")
break
case .restricted:
NSLog("cameraAuthorizationStatus=restricted")
break
case .notDetermined:
NSLog("cameraAuthorizationStatus=notDetermined")
// Prompting user for the permission to use the camera.
AVCaptureDevice.requestAccess(forMediaType: cameraMediaType) { granted in
DispatchQueue.main.sync {
if granted {
// do something
} else {
// do something else
}
}
}
}
}
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)
}
}
}
Und dann, um es zu benutzen, tust du es
AVCaptureDevice.authorizeVideo(completion: { (status) in
//Your work here
})
Geben Sie zuerst den NSCameraUsageDescription-Schlüssel in Info.plist an. Überprüfen Sie dann AVAuthorizationStatus, falls autorisiert, und zeigen Sie dann den UIImagePickerController an. Es wird klappen.