ios - CIContext 初始化崩溃
<p><p><strong>背景:</strong>
我正在运行一个带有以下两个选项的 swift 2 应用程序。</p>
<p><em>选项 A:</em>
用户可以输入一个数字登录。在这种情况下,他/她的图片显示在 UIImageView 中。</p>
<p><em>选项 B:</em>
用户可以使用 NFC 标签登录。在这种情况下,UIImageView 被替换为显示实时摄像头流的摄像头层,并使用 CIContext 在按钮按下时捕获图像。</p>
<p><strong>问题:</strong>
我面临的问题是,有时,当我选择选项 A(不使用相机层)时,应用程序崩溃。由于我无法确定地重现崩溃,因此我陷入了死胡同,无法理解应用程序崩溃的原因。</p>
<p><strong>编辑:</strong>相机图层在两个选项中都使用,但隐藏在选项 A 中。</p>
<p>Crashlytics 生成以下崩溃日志:</p>
<pre><code>0 libswiftCore.dylib specialized _fatalErrorMessage(StaticString, StaticString, StaticString, UInt) -> () + 44
1 CameraLayerView.swift line 20 CameraLayerView.init(coder : NSCoder) -> CameraLayerView?
2 CameraLayerView.swift line 0 @objc CameraLayerView.init(coder : NSCoder) -> CameraLayerView?
3 UIKit - + 248
32UIKit UIApplicationMain + 208
33AppDelegate.swift line 17 main
34libdispatch.dylib (Missing)
</code></pre>
<p>我在 CameraLayerView 中检查了第 20 行,但这只是一个初始化语句</p>
<pre><code>private let ciContext = CIContext(EAGLContext: EAGLContext(API: .OpenGLES2))
</code></pre>
<p>下面提到的是 CameraLayerView 文件。任何帮助将不胜感激</p>
<pre><code>var captureSession = AVCaptureSession()
var sessionOutput = AVCaptureVideoDataOutput()
var previewLayer = AVCaptureVideoPreviewLayer()
private var pixelBuffer : CVImageBuffer!
private var attachments : CFDictionary!
private var ciImage : CIImage!
private let ciContext = CIContext(EAGLContext: EAGLContext(API: .OpenGLES2))
private var imageOptions : !
var faceFound = false
var image : UIImage!
override func layoutSubviews() {
previewLayer.position = CGPoint(x: self.frame.width/2, y: self.frame.height/2)
previewLayer.bounds = self.frame
self.layer.borderWidth = 2.0
self.layer.borderColor = UIColor.redColor().CGColor
}
func loadCamera() {
let camera = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
for device in camera {
if device.position == .Front {
do{
for input in captureSession.inputs {
captureSession.removeInput(input as! AVCaptureInput)
}
for output in captureSession.outputs {
captureSession.removeOutput(output as! AVCaptureOutput)
}
previewLayer.removeFromSuperlayer()
previewLayer.session = nil
let input = try AVCaptureDeviceInput(device: device as! AVCaptureDevice)
if captureSession.canAddInput(input) {
captureSession.addInput(input)
sessionOutput.videoSettings =
sessionOutput.setSampleBufferDelegate(self, queue: dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.rawValue), 0))
sessionOutput.alwaysDiscardsLateVideoFrames = true
if captureSession.canAddOutput(sessionOutput) {
captureSession.addOutput(sessionOutput)
captureSession.sessionPreset = AVCaptureSessionPresetPhoto
captureSession.startRunning()
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
switch UIDevice.currentDevice().orientation.rawValue {
case 1:
previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.Portrait
break
case 2:
previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.PortraitUpsideDown
break
case 3:
previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.LandscapeRight
break
case 4:
previewLayer.connection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft
break
default:
break
}
self.layer.addSublayer(previewLayer)
}
}
} catch {
print("Error")
}
}
}
}
func takePicture() -> UIImage {
self.previewLayer.removeFromSuperlayer()
self.captureSession.stopRunning()
return image
}
func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) {
pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, sampleBuffer, kCMAttachmentMode_ShouldPropagate)
ciImage = CIImage(CVPixelBuffer: pixelBuffer!, options: attachments as? )
if UIDevice.currentDevice().orientation == .PortraitUpsideDown {
imageOptions =
} else if UIDevice.currentDevice().orientation == .LandscapeLeft {
imageOptions =
} else if UIDevice.currentDevice().orientation == .LandscapeRight {
imageOptions =
} else {
imageOptions =
}
let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: ciContext, options: )
let features = faceDetector.featuresInImage(ciImage, options: imageOptions)
if features.count == 0 {
if faceFound == true {
faceFound = false
dispatch_async(dispatch_get_main_queue()) {
self.layer.borderColor = UIColor.redColor().CGColor
}
}
} else {
if UIDevice.currentDevice().orientation == .PortraitUpsideDown {
image = UIImage(CGImage: ciContext.createCGImage(ciImage, fromRect: ciImage.extent), scale: 1.0, orientation: UIImageOrientation.Left)
} else if UIDevice.currentDevice().orientation == .LandscapeLeft {
image = UIImage(CGImage: ciContext.createCGImage(ciImage, fromRect: ciImage.extent), scale: 1.0, orientation: UIImageOrientation.Down)
} else if UIDevice.currentDevice().orientation == .LandscapeRight {
image = UIImage(CGImage: ciContext.createCGImage(ciImage, fromRect: ciImage.extent), scale: 1.0, orientation: UIImageOrientation.Up)
} else {
image = UIImage(CGImage: ciContext.createCGImage(ciImage, fromRect: ciImage.extent), scale: 1.0, orientation: UIImageOrientation.Right)
}
if faceFound == false {
faceFound = true
for feature in features {
if feature.isKindOfClass(CIFaceFeature) {
dispatch_async(dispatch_get_main_queue()) {
self.layer.borderColor = UIColor.greenColor().CGColor
}
}
}
}
}
}
</code></pre></p>
<br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
<p><p>我测试了一个理论,它奏效了。由于 ciContext 是使用 View 初始化进行初始化的,因此应用程序似乎由于竞争条件而崩溃。我将 ciContext 的初始化移动到我的 loadCamera 方法中,此后它没有崩溃。</p>
<p><strong>更新</strong></p>
<p>我注意到的另一件事是,在互联网上的各种教程和博客文章中,语句 <code>let ciContext = CIContext(EAGLContext: EAGLContext(API: .OpenGLES2))</code> 是在两个单独的语句中声明的这样就变成了</p>
<pre><code>let eaglContext = EAGLContext(API: .OpenGLES2)
let ciContext = CIContext(EAGLContext: eaglContext)
</code></pre>
<p>我仍然不知道究竟是什么导致应用程序崩溃,但这两个更改似乎已经解决了问题</p>
<p><strong>正确答案</strong></p>
<p>终于找到了罪魁祸首。在我使用 ciContext 的 viewController 中,我有一个没有失效的计时器,因此保持对 viewController 的强引用。在随后的每次访问中,它都会创建一个新的 viewController,而前一个从未从内存中释放。这导致内存超时。一旦超过某个阈值,ciContext 初始化程序将返回 nil,因为内存不足会导致应用程序崩溃。</p></p>
<p style="font-size: 20px;">关于ios - CIContext 初始化崩溃,我们在Stack Overflow上找到一个类似的问题:
<a href="https://stackoverflow.com/questions/43314378/" rel="noreferrer noopener nofollow" style="color: red;">
https://stackoverflow.com/questions/43314378/
</a>
</p>
页:
[1]