Cant figure this one out. Everything works fine when the app is active, and than sometimes when i move the app to the background(pressing the home button) and than going back, the previewlayer freezes/stuck. Im using viewWillAppear and viewDidAppear for the set up. This is how i set everything up :
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
}
Just a quick update In 2017 if someone suffering overthinking such that thing,
Do the same thing but change your
replace it with
it will solve the issue. If not, then come back here and write down :))
Swift 4 Solution
You have to delete the camera input when the user enters the background, then restore it when they return. Take a look at this code:
Swift 4.2:
override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) setupCamera() //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. }
Roi,
I think your problem is that you are doing all the session setup and such in the viewWillAppear. Lets say that the captureSession, and the previewLayer were both alloc'd and working correctly. Now, you put app into the background and bring back.
You will immediately try to create a new captureSession, and a new previewLayer. I suspect that the old ones and the new ones are getting tangled up.
In the Apple AVCam example they do the setup in the viewDidLoad. That way it is only done once.
You should move all your setup stuff to a method and then call the method from the viewDidLoad.
bill
For future readers: this is the correct process to setting up camera inside your app.
First of all, thanks for the folks above that took their time and tried help me. They both direct me into the correct direction. Although Bill was mistaken about the
viewDidLoad
theory, he did gave the solution Apple Project.This setting up camera - the correct way - is little more complicated than I thought, follow the documentation gave me excellent results. So for the Objective-C coders:
Objective C cam project
Swift cam project
About Andrea answer, he did said some great pointers you should consider when you are creating this kind of app. Check them out - they are highly relevant (most of the things he said inside the Apple project as well).
I think that there are different things that could cause the problem:
-beginConfiguration
and-commitConfiguration
block of code. Each time you setup something in the session it will takes time to do it. Wrapping your configuration code between those method will guarantee that all the changes are committed in one shot, reducing the overall session creation timeUIApplicationDidEnterBackground
andUIApplicationWillEnterForeground
to pause and start again the session.-viewWillAppear
each time this method is called you create a session but, is not really clear from your code if you get rid of it. You should separate and balance the session creation and destroy. Provide a-setupSession
and a-tearDownSession
methods. Make sure that the setup is called only if there is no active session and make sure that when you don't need the session anymore you get rid of it by calling theteardownSession
. In SWIFT you na use a @lazy variable and destroy the session indeinit()
or-viewWillDisappear
.I undestand that is huge refactor, but I'm this way I'm pretty sure that you will experience less problems in the future.