Ios AVCaptureVideoPreviewLayer(相机预览)在移动到背景和返回后冻结/卡住
我想不出这个。 当应用程序处于活动状态时,一切正常,有时当我将应用程序移到后台(按home按钮)并返回时,previewlayer冻结/卡住。 Im使用ViewWillDisplay和ViewDidDisplay进行设置。 这就是我设置一切的方式:Ios AVCaptureVideoPreviewLayer(相机预览)在移动到背景和返回后冻结/卡住,ios,camera,preview,avcapturesession,avcapturedevice,Ios,Camera,Preview,Avcapturesession,Avcapturedevice,我想不出这个。 当应用程序处于活动状态时,一切正常,有时当我将应用程序移到后台(按home按钮)并返回时,previewlayer冻结/卡住。 Im使用ViewWillDisplay和ViewDidDisplay进行设置。 这就是我设置一切的方式: var backCamera = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) var global_device : AVCaptureDevice! var captur
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()
}
}
视图显示:
var previewLayer: AVCaptureVideoPreviewLayer?
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
previewLayer!.frame = camera_Preview.bounds
}
投资回报率
我认为您的问题在于您正在进行所有会话设置,并且会在视图中显示这些设置。假设captureSession和previewLayer都已分配且工作正常。现在,您将应用程序放在后台并带回
您将立即尝试创建一个新的captureSession和一个新的previewLayer。我怀疑旧的和新的正在纠缠不清
在Apple AVCam示例中,他们在viewDidLoad中进行设置。这样只做一次
您应该将所有设置内容移动到一个方法中,然后从viewDidLoad调用该方法
比尔我认为有不同的因素可能导致这个问题:
-beginConfiguration
和-commitConfiguration
代码块中。每次在会话中设置某些内容都需要时间。在这些方法之间包装配置代码将确保所有更改都在一次提交中提交,从而缩短整个会话创建时间uiapplicationidenterbackground
的观察者,然后UIApplicationWillEnterForeground
暂停并重新启动会话-view中创建会话,但如果您删除了会话,则代码中的会话并不清晰。您应该分离并平衡会话创建和销毁。提供-setupSession
和-tearDownSession
方法。确保仅当没有活动会话时才调用安装程序,并确保当您不再需要会话时,可以通过调用teardownSession
来摆脱会话。在SWIFT中,使用@lazy变量并在deinit()
或-viewwilldiscover
中销毁会话
我不理解这是一个巨大的重构,但我相信,通过这种方式,我相信你将来会遇到更少的问题。对于未来的读者:这是在你的应用程序中设置摄像头的正确过程 首先,感谢上面那些花时间帮助我的人。他们都指引我进入正确的方向。尽管比尔对
viewDidLoad
理论有误解,但他确实给出了苹果项目的解决方案
这个设置相机-正确的方法-比我想象的要复杂一点,按照文档给了我极好的效果。因此,对于Objective-C编码器:
关于安德列的回答,他说了一些你在创建这种应用程序时应该考虑的好的指针。看看它们——它们是高度相关的(他在苹果项目中所说的大部分内容也是如此)。如果有人过度思考这种事情,请在2017年快速更新 做同样的事情,但改变你的想法
stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
换成
stillImageOutput!.outputSettings = [((kCVPixelBufferPixelFormatTypeKey as NSString) as String):NSNumber(value:kCVPixelFormatType_32BGRA)]
它将解决这个问题。如果没有,请返回此处并写下:)Swift 4解决方案 当用户进入背景时,您必须删除相机输入,然后在用户返回时将其恢复。请看下面的代码:
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:
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.
}
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)
}
}
我也遇到了这个问题,我通过将它添加到我的ViewWillDisplay和viewWillDissapear中修复了我的问题。希望这有帮助
var session = AVCaptureSession()
override func viewWillAppear(_ animated: Bool) {
session.startRunning()
}
override func viewWillDisappear(_ animated: Bool) {
session.stopRunning()
}
比尔,谢谢你的回复。应用程序的进出是否会重新触发WillAspect等方法?实际上我刚刚检查了它,在ViewWillAspect中设置了一个断点,当我重新打开appRight时,似乎不会再次触发。最小化和返回时,ViewWillDisplay似乎不会被激发。但是,如果您继续使用另一个视图控制器,它将是。这可能是问题的一部分吗?你的意思是如果我从原始视图移动后出去?如果你在导航控制器中,按下第二个屏幕,然后按下后退按钮,你将导致我描述的问题。您的捕获会话和预览层将被重新创建。您可能希望将捕获会话创建移动到viewDidLoad。嘿!我使用基于苹果的文档来修复我的代码。你说的大部分我都加了,有必要做拆卸部分吗?因为我没有这样做,而且现在看起来很有效,谢谢!“目标C cam项目”的链接已断开。答案现在对任何人都没有用处。你能更新链接吗?或者在答案中显示解决方案?链接已更新。未来展望:如果链接再次中断,该项目将被称为“AVCam iOS”——谷歌会立即找到它,或者在developer.apple.com上查看它。如果苹果有像样的文档,事情可能会变得非常简单。像往常一样抛出示例代码或编写糟糕的文档对开发人员没有任何好处。想象一个没有stackoverflow的世界,没有一行代码可以创建。你知道原因吗?你能提供简单而简短的解决方案吗?