无法想出这一个。 当应用程序处于活动状态时,一切正常,而当我将应用程序移动到后台(按下主页按钮)时,有时,而不是返回,预览层会冻结/卡住。 我使用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
}
答案 0 :(得分:3)
对于未来的读者:这是在您的应用中设置相机的正确过程。
首先,感谢上面那些花时间尝试帮助我的人们。他们都指引我走向正确的方向。虽然比尔错误地认为viewDidLoad
理论,但他确实给出了Apple Project的解决方案。
这个设置相机 - 正确的方法 - 比我想象的复杂一点,按照文档给了我很好的结果。所以对于Objective-C编码器:
关于Andrea的答案,他确实说过在创建这种应用程序时应该考虑的一些很好的指示。检查它们 - 它们是高度相关的(他在Apple项目中也说过的大部分内容)。
答案 1 :(得分:3)
快速更新2017年如果有人遭遇过度思考这样的事情,
做同样的事情,但改变你的
stillImageOutput!.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
替换为
stillImageOutput!.outputSettings = [((kCVPixelBufferPixelFormatTypeKey as NSString) as String):NSNumber(value:kCVPixelFormatType_32BGRA)]
它将解决问题。如果没有,那么回到这里写下来:))
答案 2 :(得分:2)
投资回报率,
我认为您的问题是您正在进行所有会话设置,例如viewWillAppear。让我们说captureSession和previewLayer都是alloc并且正常工作。现在,您将应用程序放入后台并返回。
您将立即尝试创建一个新的captureSession和一个新的previewLayer。我怀疑旧的和新的都在纠结。
在Apple AVCam示例中,他们在viewDidLoad中进行设置。这样它只做一次。
您应该将所有设置内容移动到方法,然后从viewDidLoad调用该方法。
纸币
答案 3 :(得分:1)
我认为有不同的事情可能导致问题:
-beginConfiguration
和-commitConfiguration
代码块中包装您正在执行的所有配置。每次在会话中设置某些内容时,都需要时间。在这些方法之间包装配置代码将保证一次性提交所有更改,从而减少整个会话创建时间UIApplicationDidEnterBackground
和UIApplicationWillEnterForeground
的观察者身份注册您的课程,暂停并重新开始会话。-viewWillAppear
中创建会话,但是如果您将其删除,则无法从代码中清楚地看到该会话。您应该分离和平衡会话创建和销毁。提供-setupSession
和-tearDownSession
方法。确保只有在没有活动会话的情况下才会调用设置,并确保当您不再需要会话时,可以通过调用teardownSession
来解除它。在SWIFT中你可以使用@lazy变量并在deinit()
或-viewWillDisappear
中销毁会话。我认为这是一个巨大的重构,但我是这样的,我很确定你将来会遇到更少的问题。
答案 4 :(得分:1)
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)
}
}
答案 5 :(得分:0)
我也遇到了这个问题,我通过将其添加到viewWillAppear和viewWillDissapear中来修复了我的问题。希望这会有所帮助
var session = AVCaptureSession()
override func viewWillAppear(_ animated: Bool) {
session.startRunning()
}
override func viewWillDisappear(_ animated: Bool) {
session.stopRunning()
}