2016-06-08 3 views
0

나는 captureStillImageAsynchronouslyFromConnection() - 방법을 통해 카메라로 사진을 찍을 수있는 기능이 있습니다. 캡처 한 이미지는 capture() - 메소드의 반환 값입니다.캡처 한 사진을 메인 스레드로 가져 오는 방법은 무엇입니까?

캡쳐 한 사진을 내 ViewController의 변수에 저장하고 다른 뷰 콘트롤러로 segue를 수행하여 사진을 표시하려고합니다. 이것은 작동하지 않는 것 같아 fatal error: unexpectedly found nil while unwrapping an Optional value - 오류가 발생합니다.

나는 var photo: UIImage!nil 인 것을 알고 있지만, performSegue... 함수를 호출하기 전에 어떻게 사진 데이터를 메인 스레드로 가져올 수 있습니까?

내 사진 기능 (내 내부 CameraSession 클래스)과 세션 큐 :

var sessionQueue = dispatch_queue_create("CameraSession", DISPATCH_QUEUE_SERIAL) 

func capture(saveToGallery save: Bool) -> UIImage { 
    var capturedImage = UIImage() 

    let connection = self.output.connectionWithMediaType(AVMediaTypeVideo) 
    connection.videoOrientation = .Portrait 

    dispatch_async(sessionQueue, { 
     self.output.captureStillImageAsynchronouslyFromConnection(
      connection, completionHandler: { 
       (imageDataSampleBuffer: CMSampleBuffer?, error: NSError?) -> Void in 
       if imageDataSampleBuffer != nil { 
        let imageData: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) 
         self.capturedImage = UIImage(data: imageData) 

        if save { 
         UIImageWriteToSavedPhotosAlbum(self.capturedImage!, nil, nil, nil) 
        } 
       } 
      } 
     ) 
    }) 

    return self.capturedImage! 
} 

의 ViewController 클래스에 내 기능 :

func capture() { 
    let photo = cameraSession.capture(saveToGallery: true) 
    performSegueWithIdentifier("showPhoto", sender: self) // This will switch to another ViewController, which shows the captured photo. 
} 

답변

0

비동기 당신을 사진을 캡처하고 있기 때문에 함수가 도달하기 전에

return self.capturedImage! 

에 도달 할 것이며, f.capturedImage는 nil입니다. 이미지 데이터가 반환 된 후 어딘가에 segue를 처리하는 논리를 이동해야합니다. 은있는 UIImage를 돌려 직접 다음

func capture(saveToGallery save: Bool, callback:UIImage -> Void) -> Void 

대신의 콜백에 대한 인수로 전달 :

let imageData: NSData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer) 
    self.capturedImage = UIImage(data: imageData) 

if save { 
    UIImageWriteToSavedPhotosAlbum(self.capturedImage!, nil, nil, nil) 
} 

callback(self.capturedImage) 

이 캡처 방법에 인수로 콜백을 추가하여 수행 할 아마도 가장 쉬운 방법입니다 (: _) 메소드있는 UIImage 걸리는 두 번째 매개 변수로 블록 캡처를 통과

func capture() { 
    let photo = cameraSession.capture(saveToGallery: true, callback: { 
    (photo: UIImage) -> Void in 
    //save your photo locally in your UIViewController class here if you need to 
    performSegueWithIdentifier("showPhoto", sender: self) 
    }) 
} 
+0

이미지가의 ViewController 클래스에서 촬영되지 않은, 그래서 나는를 추가 할 수 없습니다 그것에 segue. 'self.capturedImage'가 nil이 아니고 반환 할 때까지 기다리는 기능을 강요 할 수 있습니까? – user3653164

+0

Gargoyle이 설명하는 것과 같은 것을 권하고, 블록을 캡처 메소드의 두 번째 인수로 전달합니다. 이 아이디어를 반영하여 내 대답을 업데이트했습니다. – J2K

0

: 귀하의 UIViewController 캡처 방법은 같을 것입니다. 캡처 한 이미지를 만들면 이미지를 저장 한 후 이미지와 함께 블록으로 전달합니다. 전화하기 전에 기본 대기열로 보내십시오. 당신은이 같은 주 (UI) 스레드를 요청

func capture() { 
    cameraSession.capture(saveToGallery: true) { 
     [unowned self] image in 
     self.myCapturedImage = image 
     self.performSegueWithIdentifier("showPhoto", sender: self) 
    } 
} 
+0

"전화하기 전에 기본 대기열로 보내야하는 부분이 무엇입니까?" – user3653164

+0

세션 대기열에 이미지를 저장 한 후. 메인 큐에 dispatch_async를 수행하고 그 디스패치 블록 내에서 당신에게 전달 된 블록을 호출하십시오. – Gargoyle

+0

여전히 내 ViewController-Class의'photo' 변수에 대해 동일한 오류가 발생합니다. 콜백/완료 블록을 사용하고 dispatch_async를 사용하여 내 'completion (image : self.capturedImage!)'을 수행하더라도 여전히 비어 있습니다. – user3653164

0

: 그럼 당신은 더 같은이있을 것이다

dispatch_async(dispatch_get_main_queue(), ^{ 
    //Do something in main thread 
});