AVCaptureVideoPreviewLayer(相机预览)冻结/卡住移动到后台和后退

不能把这一个出来。 一切正常,当应用程序处于活动状态, 有时当我将应用程序移动到背景(按主页button),而不是返回时,预览图层冻结/卡住。 我使用viewWillAppear和viewDidAppear进行设置。 这是我如何设置一切:

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 } 

对于未来的读者:这是在您的应用程序内设置相机的正确过程。

首先,感谢上面那些花费时间,试图帮助我的人。 他们都指引我进入正确的方向。 尽pipe比尔对“ viewDidLoad理论认为是错误的,但他确实给出了苹果计划的解决scheme。

这个设置摄像头 – 正确的方法 – 比我想象的要复杂一点,按照文档给我出色的结果。 所以对于Objective-C编码器:

目标C cam项目

Swift凸轮项目

关于Andrea的回答,他曾经说过,当你创build这种应用程序时,你应该考虑一些伟大的指针。 检查出来 – 他们是高度相关的(他在苹果项目中说的大部分内容)。

投资回报率,

我认为你的问题是你正在做所有的会话设置,并在viewWillAppear。 可以说captureSession和previewLayer都被分配和正常工作。 现在,你把应用程序放到后台,然后回来。

您将立即尝试创build一个新的CaptureSession和一个新的previewLayer。 我怀疑旧的和新的都混在一起了。

在Apple AVCam示例中,他们在viewDidLoad中进行设置。 那样它只做一次。

你应该把所有的设置东西移动到一个方法,然后从viewDidLoad中调用方法。

法案

我认为有不同的事情可能导致这个问题:

  1. 您应该将所有正在进行的configuration封装在-beginConfiguration-commitConfiguration代码块中。 每次在会话中设置一些东西都需要时间来完成。 在这些方法之间包装你的configuration代码将保证所有的改变都是一次性提交的,从而减less了整个会话创build时间
  2. 暂停会话是一个很好的,当你去背景。 注册你的类作为观察者到UIApplicationDidEnterBackgroundUIApplicationWillEnterForeground暂停并重新开始会话。
  3. 你在-viewWillAppear创build会话,每次这个方法被调用时,你创build一个会话,但是,如果你摆脱它,从你的代码是不是很清楚。 你应该分开和平衡会话创build和销毁。 提供一个-setupSession和一个-tearDownSession方法。 确保仅在没有活动会话时调用该设置,并确保不再需要该会话时,通过调用teardownSession来清除该设置。 在SWIFT中,您不使用@lazyvariables,并在deinit()-viewWillDisappear销毁会话。
  4. 创build或使用SYNC队列可能是非常有用的创build和销毁会话是一项密集型任务,您通常宁愿将其放在后台队列中,此外还有助于同步所有涉及会话的方法。 创build你自己的同步队列将保证例如build立会话呼叫和拆除呼叫之间的同步,只有当另一个呼叫完成时才呼叫。

我觉得这是一个巨大的重构,但是我很确定你将会遇到更less的问题。

只是一个快速更新在2017年,如果有人遭受过度这样的事情,

做同样的事情,但改变你的

 stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG] 

用它replace

 stillImageOutput!.outputSettings = [((kCVPixelBufferPixelFormatTypeKey as NSString) as String):NSNumber(value:kCVPixelFormatType_32BGRA)] 

它会解决这个问题。 如果没有,那就回来再写下来:))