2017-04-10 7 views
2

背景: 私は以下の2つのオプションでswift 2アプリケーションを実行しています。CIContextの初期化クラッシュ

オプションA: ユーザがサインインする番号を入力することができ、この場合には、彼/彼女の画像がUIImageViewに示されています。 。

オプションB:ユーザーがサインインするためにNFCタグを使用することができ、この場合 、UIImageViewは、ライブカメラの流れを示しており、ボタンを押して画像をキャプチャするCIContextを使用してカメラの層に置き換えられます。

問題: 私が直面してる問題であることを時々、私は(カメラレイヤーを使用していない)オプションAを選択すると、アプリがクラッシュします。私は決定的にクラッシュを再現することができないので、私はアプリがクラッシュする理由を理解するために行き詰まった。

EDIT:

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 -[UIClassSwapper initWithCoder:] + 248 
32 UIKit UIApplicationMain + 208 
33 AppDelegate.swift line 17 main 
34 libdispatch.dylib (Missing) 

私はCameraLayerViewでライン#20をチェックしました:カメラ層は、両方のオプションで使用されているが、

CrashlyticsオプションAに隠されているは、次のクラッシュログを生成し、それは単に初期化文です。

private let ciContext = CIContext(EAGLContext: EAGLContext(API: .OpenGLES2)) 

以下にCameraLayerViewファイルを示します。任意の助けを歓迎する

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 : [String : AnyObject]! 

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 = [String(kCVPixelBufferPixelFormatTypeKey) : Int(kCVPixelFormatType_32BGRA)] 
        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? [String : AnyObject]) 
    if UIDevice.currentDevice().orientation == .PortraitUpsideDown { 
     imageOptions = [CIDetectorImageOrientation : 8] 
    } else if UIDevice.currentDevice().orientation == .LandscapeLeft { 
     imageOptions = [CIDetectorImageOrientation : 3] 
    } else if UIDevice.currentDevice().orientation == .LandscapeRight { 
     imageOptions = [CIDetectorImageOrientation : 1] 
    } else { 
     imageOptions = [CIDetectorImageOrientation : 6] 
    } 
    let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: ciContext, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) 
    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 
        } 
       } 
      } 
     } 
    } 
} 
+0

クラッシュをローカルで(Xcodeで)再生することができますか、またはユーザーのデバイスでのみ再生できますか?もしそうなら、コンソールログは何を言っていますか? –

+0

自分でエラーを再現できませんでした。このクラッシュにつながる一連の出来事のパターンを見つけることもできませんでした。それは頻繁に起こることはありませんが、それが起こったとき、それはアプリケーションを再起動させます(アプリのクラッシュは一般的にアプリケーションを再起動するのではなくクラッシュさせるので、それ自体は奇妙な動作です) – Malik

+0

私はこれまで聞いたことがありませんiOSアプリケーションが「自動的にクラッシュして再起動する」(システム「アプリ」Springboard以外) –

答えて

0

私は理論をテストし、それは働いた。 ciContextはビューの初期化で初期化されていたため、アプリが競合状態でクラッシュしているように見えました。私はciContextの初期化をloadCameraメソッドに移しました。それ以来、クラッシュしていません。

UPDATE

私が気づいたもう一つは、それはまだ

let eaglContext = EAGLContext(API: .OpenGLES2) 
let ciContext = CIContext(EAGLContext: eaglContext) 

Iになったように、インターネット上のさまざまなチュートリアルやブログ記事に、声明は二つの別々のステートメントで宣言された、ということでしたアプリが最初にクラッシュする原因となったのは正確ではありませんが、この2つの変更は問題を解決したようです。

正解

最終的には、犯人が見つかりました。私のviewControllerでは、ciContextを使用していましたので、無効にしていないタイマーがあり、viewControllerへの強い参照を保持していました。それ以降のすべての訪問では、新しいviewControllerが作成され、前のビューはメモリから解放されませんでした。これは、メモリが時間外にいっぱいになった。一定のスレッショルドを超えると、ciContextのintialiserはメモリ不足のためnilを返し、アプリケーションをクラッシュさせます。

関連する問題