Tout fonctionne bien lorsque l’application est active et que parfois lorsque je déplace l’application en arrière-plan (en appuyant sur le bouton principal) et que pour revenir en arrière, la couche de prévisualisation se bloque/coincé. J'utilise viewWillAppear et viewDidAppear pour la configuration. Voici comment j'ai tout configuré:
var backCamera = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
var global_device : AVCaptureDevice!
var captureSession: AVCaptureSession?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
captureSession = AVCaptureSession()
captureSession!.sessionPreset = AVCaptureSessionPresetPhoto
CorrectPosition = AVCaptureDevicePosition.Back
for device in backCamera {
if device.position == AVCaptureDevicePosition.Back {
global_device = device as! AVCaptureDevice
CorrectPosition = AVCaptureDevicePosition.Back
break
}
}
configureCamera()
var error: NSError?
var input = AVCaptureDeviceInput(device: global_device, error: &error)
if error == nil && captureSession!.canAddInput(input) {
captureSession!.addInput(input)
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if captureSession!.canAddOutput(stillImageOutput) {
captureSession!.addOutput(stillImageOutput)
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
var bounds:CGRect = camera_Preview.layer.bounds
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
previewLayer?.bounds = bounds
previewLayer?.position = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds))
camera_Preview.layer.addSublayer(previewLayer)
self.view.bringSubviewToFront(camera_Preview)
self.view.bringSubviewToFront(nan_view)
captureSession!.startRunning()
}
}
ViewDidAppear:
var previewLayer: AVCaptureVideoPreviewLayer?
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
previewLayer!.frame = camera_Preview.bounds
}
Pour les futurs lecteurs: il s'agit du processus approprié pour configurer la caméra dans votre application.
Tout d'abord, merci aux personnes ci-dessus qui ont pris leur temps et ont essayé de m'aider. Ils me dirigent tous les deux dans la bonne direction. Bien que Bill se soit trompé sur la théorie viewDidLoad
, il a donné la solution Apple Project.
Cette configuration de la caméra - la manière correcte - est un peu plus compliquée que je ne le pensais, suivre la documentation m'a donné d'excellents résultats. Donc pour les codeurs Objective-C:
À propos de la réponse d’Andrea, il a indiqué que vous devriez prendre en considération d’excellents conseils lorsque vous créez ce type d’application. Vérifiez-les - ils sont très pertinents (la plupart des choses qu'il a dites dans le projet Apple également).
Juste une mise à jour rapide en 2017 si quelqu'un souffre trop de penser à ça,
Faites la même chose mais changez votre
stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
le remplacer par
stillImageOutput!.outputSettings = [((kCVPixelBufferPixelFormatTypeKey as NSString) as String):NSNumber(value:kCVPixelFormatType_32BGRA)]
cela résoudra le problème. Si non, alors reviens ici et écris :))
Roi,
Je pense que votre problème est que vous effectuez toute la configuration de la session et telle dans le viewWillAppear. Disons que la captureSession et le previewLayer étaient tous deux alloués et fonctionnaient correctement. Maintenant, vous mettez l'application en arrière-plan et ramenez-la.
Vous allez immédiatement essayer de créer une nouvelle captureSession et un nouveau previewLayer. Je soupçonne que les anciens et les nouveaux s'emmêlent.
Dans l'exemple Apple AVCam, ils effectuent la configuration dans viewDidLoad. De cette façon, ce n'est fait qu'une fois.
Vous devez déplacer tous vos éléments de configuration vers une méthode, puis appeler la méthode à partir de viewDidLoad.
facture
Je pense qu'il y a différentes choses qui pourraient causer le problème:
-beginConfiguration
et -commitConfiguration
. Chaque fois que vous configurez quelque chose dans la session, cela prend du temps. En plaçant votre code de configuration entre ces méthodes, vous garantissez que toutes les modifications sont validées en une seule fois, ce qui réduit le temps de création de la sessionUIApplicationDidEnterBackground
et UIApplicationWillEnterForeground
pour mettre en pause et redémarrer la session.-viewWillAppear
chaque fois que cette méthode est appelée, vous créez une session, mais votre code ne le clarifie pas vraiment si vous vous en débarrassez. Vous devez séparer et équilibrer la création et la destruction de la session. Fournissez les méthodes -setupSession
et -tearDownSession
. Assurez-vous que la configuration est appelée uniquement s'il n'y a pas de session active et assurez-vous que lorsque vous n'en avez plus besoin, vous vous en débarrassez en appelant le teardownSession
. Dans Swift, vous utilisez une variable @lazy et détruisez la session dans deinit()
ou -viewWillDisappear
.Je comprends que c'est un refactor énorme, mais je suis comme ça, je suis à peu près sûr que vous aurez moins de problèmes à l'avenir.
Solution Swift 4
Vous devez supprimer l'entrée de la caméra lorsque l'utilisateur entre en arrière-plan, puis la restaurer à son retour. Jetez un oeil à ce code:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
createCameraPreview() //Call the setup of the camera here so that if the user enters the view controller from another view controller, the camera is established.
notificationCenter() //Call the notification center function to determine when the user enters and leaves the background.
}
func notificationCenter() {
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: .UIApplicationWillResignActive , object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(openedAgain), name: .UIApplicationDidBecomeActive, object: nil)
}
@objc func openedAgain() {
createCameraPreview() // This is your function that contains the setup for your camera.
}
@objc func willResignActive() {
print("Entered background")
let inputs = captureSession!.inputs
for oldInput:AVCaptureInput in inputs {
captureSession?.removeInput(oldInput)
}
}
Swift 4.2:
remplacez func viewWillAppear (_ animé: Bool) { super.viewWillAppear (animé) setupCamera () // createCameraPreview () // Appelez la configuration de la caméra ici pour qu'elle si l'utilisateur entre le contrôleur de vue à partir d'un autre contrôleur de vue, la caméra est établie. notificationCenter () // Appelez la fonction de centre de notification pour déterminer quand l'utilisateur entre et quitte l'arrière-plan. }
func notificationCenter() {
NotificationCenter.default.addObserver(self, selector: #selector(willResignActive), name: UIApplication.willResignActiveNotification , object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(openedAgain), name: UIApplication.didBecomeActiveNotification, object: nil)
}
@objc func openedAgain() {
setupCamera() //This is your function that contains the setup for your camera.
}
@objc func willResignActive() {
print("Entered background")
let inputs = captureSession.inputs
for oldInput:AVCaptureInput in inputs {
captureSession.removeInput(oldInput)
}
}