2016-06-08 4 views
0

У меня есть функция для захвата фотографии с помощью камеры с помощью метода captureStillImageAsynchronouslyFromConnection(). Захваченное изображение - мое возвращаемое значение для метода capture().Как получить снятое фото в основной поток?

Я хочу сохранить захваченную фотографию в переменную в моем ViewController, а затем выполнить segue в другой ViewController, который покажет фотографию. Это не работает, я получаю 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! 

до того, как фотография была сделана, и sel f.capturedImage - нуль. Вы должны переместить свою логику, которая обрабатывает segue где-то после возвращения данных изображения. Это, вероятно, проще всего выполнить путем добавления обратного вызова в качестве аргумента в ваш метод захвата:

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

, а затем вместо того, чтобы непосредственно возвращая UIImage, передать его в качестве аргумента обратного вызова:

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

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

callback(self.capturedImage) 

Ваш UIViewController метод захвата будет выглядеть примерно так:

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-класса, поэтому я не могу добавить перейдите к нему. Можно ли заставить мою функцию ждать, пока 'self.capturedImage' не будет равен нулю, а затем вернет его? – user3653164

+0

Я бы рекомендовал что-то вроде того, что описывает Гаргульи, передавая блок в качестве второго аргумента вашему методу захвата. Обновленный мой ответ, чтобы отразить эту идею. – J2K

0

Пройди свой захват (: _) метод блок-в качестве второго параметра, который принимает UIImage. Когда вы создадите захваченное изображение, после его сохранения вызовите тот, который передается в блоке с изображением. Просто отправьте его в основную очередь, прежде чем позвонить. Тогда вы бы что-то подобное:

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

. Я все еще получаю ту же ошибку для переменной 'photo' в моем классе ViewController. Он по-прежнему остается пустым, даже если я делаю это с блоком обратного вызова/завершения и dispatch_async для моего завершения (image: self.capturedImage!) ' – user3653164

0

Вы запрашиваете основной (UI) нить вроде этого:

dispatch_async(dispatch_get_main_queue(), ^{ 
    //Do something in main thread 
}); 
Смежные вопросы