AVCaptureSession运行时崩溃.致命错误:在展开可选值(lldb)时意外发现nil



致命错误:在展开可选值(lldb)时意外发现nil

这条消息是因为我的变量被设置为nil,但代码希望它不是nil。但我没有解决办法。当我从铸造和分配中删除问号时,会发生其他错误。

螺纹1致命错误if deviceInput == nil!处绿色突出显示的行。和在CCD_ 2调用处的另一个错误绿色突出显示的行。

应用程序启动,相机手电筒根据我的代码自动打开,但随后应用程序崩溃。应用程序一直在运行,卡在启动屏幕上,火炬仍然打开。

你能看看设置了多少摄像头会话并告诉我出了什么问题吗?感谢

import UIKit
import Foundation
import AVFoundation
import CoreMedia
import CoreVideo
class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
let captureSession = AVCaptureSession()
var captureDevice : AVCaptureDevice?
var validFrameCounter: Int = 0
// for sampling from the camera
enum CurrentState {
case statePaused
case stateSampling
}
var currentState = CurrentState.statePaused
override func viewDidLoad() {
super.viewDidLoad()
captureSession.sessionPreset = AVCaptureSessionPresetHigh
let devices = AVCaptureDevice.devices()
// Loop through all the capture devices on this phone
for device in devices {
// Make sure this particular device supports video
if (device.hasMediaType(AVMediaTypeVideo)) {
// Finally check the position and confirm we've got the back camera
if(device.position == AVCaptureDevicePosition.Back) {
captureDevice = device as? AVCaptureDevice
if captureDevice != nil {
//println("Capture device found")
beginSession() // fatal error
}
}
}
}
}
// configure device for camera and focus mode

// start capturing frames
func beginSession() {
// Create the AVCapture Session
var err : NSError? = nil
captureSession.addInput(AVCaptureDeviceInput(device: captureDevice, error: &err))
if err != nil {
println("error: (err?.localizedDescription)")
}
// Automatic Switch ON torch mode
if  captureDevice!.hasTorch {
// lock your device for configuration
captureDevice!.lockForConfiguration(nil)
// check if your torchMode is on or off. If on turns it off otherwise turns it on
captureDevice!.torchMode = captureDevice!.torchActive ? AVCaptureTorchMode.Off : AVCaptureTorchMode.On
// sets the torch intensity to 100%
captureDevice!.setTorchModeOnWithLevel(1.0, error: nil)
// unlock your device
captureDevice!.unlockForConfiguration()
}
// Create a AVCaptureInput with the camera device
var deviceInput : AVCaptureInput = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &err) as! AVCaptureInput
if deviceInput == nil! {   // fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
println("error: (err?.localizedDescription)")
}
// Set the output
var videoOutput : AVCaptureVideoDataOutput = AVCaptureVideoDataOutput()
// create a queue to run the capture on
var captureQueue : dispatch_queue_t = dispatch_queue_create("captureQueue", nil)
// setup ourself up as the capture delegate
videoOutput.setSampleBufferDelegate(self, queue: captureQueue)
// configure the pixel format
videoOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String : Int(kCVPixelFormatType_32BGRA)]
// kCVPixelBufferPixelFormatTypeKey is a CFString btw.
// set the minimum acceptable frame rate to 10 fps
captureDevice!.activeVideoMinFrameDuration = CMTimeMake(1, 10)
// and the size of the frames we want - we'll use the smallest frame size available
captureSession.sessionPreset = AVCaptureSessionPresetLow
// Add the input and output
captureSession.addInput(deviceInput)
captureSession.addOutput(videoOutput)

// Start the session
captureSession.startRunning()

func setState(state: CurrentState){
switch state
{
case .statePaused:
// what goes here? Something like this?
UIApplication.sharedApplication().idleTimerDisabled = false
case .stateSampling:
// what goes here? Something like this?
UIApplication.sharedApplication().idleTimerDisabled = true  
}
}
// sampling from the camera
currentState = CurrentState.stateSampling

// stop the app from sleeping
UIApplication.sharedApplication().idleTimerDisabled = true
// update our UI on a timer every 0.1 seconds
NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
func stopCameraCapture() {
captureSession.stopRunning()
}

// pragma mark Pause and Resume of detection
func pause() {
if currentState == CurrentState.statePaused {
return
}
// switch off the torch
if captureDevice!.isTorchModeSupported(AVCaptureTorchMode.On) {
captureDevice!.lockForConfiguration(nil)
captureDevice!.torchMode = AVCaptureTorchMode.Off
captureDevice!.unlockForConfiguration()
}
currentState = CurrentState.statePaused
// let the application go to sleep if the phone is idle
UIApplication.sharedApplication().idleTimerDisabled = false
}

func resume() {
if currentState != CurrentState.statePaused {
return
}
// switch on the torch
if captureDevice!.isTorchModeSupported(AVCaptureTorchMode.On) {
captureDevice!.lockForConfiguration(nil)
captureDevice!.torchMode = AVCaptureTorchMode.On
captureDevice!.unlockForConfiguration()
}
currentState = CurrentState.stateSampling
// stop the app from sleeping
UIApplication.sharedApplication().idleTimerDisabled = true
}
}
}

查看您的代码,您应该随时尝试摆脱使用!强制展开选项的习惯,特别是为了"编译"。一般来说,如果你发现自己在写if something != nil,可能有更好的方法来写你想要的东西。试着看看这个答案中的例子,看看一些习语可以复制。你可能也会发现这个答案对高级解释选项为什么有用很有用很有用。

AVCaptureDeviceInput.deviceInputWithDevice返回一个AnyObject,您将使用以下行强制将其转换为AVCaptureInput

var deviceInput = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &err) as! AVCaptureInput

(顺便说一下,你不需要说明deviceInput的类型,Swift可以从右边的值推导出来)

当您编写as!时,您告诉编译器"不要和我争论,强制结果为AVCaptureInput类型,不要问任何问题"。如果返回的是不同类型的东西,你的应用程序将崩溃并出现错误。

但在下一行,你写道:

if deviceInput == nil! {

事实上,我对这个汇编感到非常惊讶!但事实证明它确实如此,它崩溃也就不足为奇了。强制展开一个nil的值会崩溃,而你是以它最纯粹的形式来做这件事的,强制展开nil文字:)

问题是,您已经指出deviceInput是一个非可选类型AVCaptureInput。强制铸造结果可能不是正确的做法

例如,如果设备因不再可用或正在使用而无法打开,则此方法返回nil,可选的outError参数指向描述问题的NSError

正确的处理方法是检查结果是否为nil,并采取适当的行动。所以你想做一些类似的事情:

if let deviceInput = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &err) as? AVCaptureInput
// use deviceInput
}
else {
println("error: (err?.localizedDescription)")
}

最新更新