私のビューコントローラからコードを抽出して、DRYを可能なコードとして維持しています。次のようにするときには正常に動作します:AvCaptureSessionコード抽出エラー
class InitialRegistrationViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, NVActivityIndicatorViewable {
var session: AVCaptureSession?
var stillImageOutput: AVCaptureStillImageOutput?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if Platform.isPhone {
session = AVCaptureSession()
session!.sessionPreset = AVCaptureSessionPresetPhoto
var frontCamera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
let availableCameraDevices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo)
for device in availableCameraDevices as! [AVCaptureDevice] {
if device.position == .front {
frontCamera = device
}
}
var error: NSError?
var input: AVCaptureDeviceInput!
do {
input = try AVCaptureDeviceInput(device: frontCamera)
} catch let error1 as NSError {
error = error1
input = nil
print(error!.localizedDescription)
}
if error == nil && session!.canAddInput(input) {
session!.addInput(input)
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput?.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if session!.canAddOutput(stillImageOutput) {
session!.addOutput(stillImageOutput)
session!.startRunning()
}
}
}
}
func capturePhoto() {
if let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo) {
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) -> Void in
if sampleBuffer != nil {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let dataProvider = CGDataProvider(data: imageData as! CFData)
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
let image = UIImage(cgImage: cgImageRef!, scale: 1.0, orientation: UIImageOrientation.right)
self.profileImage.image = image
}
})
}
}
}
しかし、私は以下のようなヘルパーに抽出します。
輸入のUIKit 輸入AVFoundation InitialRegistrationViewControllerに私が呼ん
class ProfilePhoto {
var session: AVCaptureSession?
var stillImageOutput: AVCaptureStillImageOutput?
func startSession() {
if Platform.isPhone {
session = AVCaptureSession()
session!.sessionPreset = AVCaptureSessionPresetPhoto
var frontCamera = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
let availableCameraDevices = AVCaptureDevice.devices(withMediaType: AVMediaTypeVideo)
for device in availableCameraDevices as! [AVCaptureDevice] {
if device.position == .front {
frontCamera = device
}
}
var error: NSError?
var input: AVCaptureDeviceInput!
do {
input = try AVCaptureDeviceInput(device: frontCamera)
} catch let error1 as NSError {
error = error1
input = nil
print(error!.localizedDescription)
}
if error == nil && session!.canAddInput(input) {
session!.addInput(input)
stillImageOutput = AVCaptureStillImageOutput()
stillImageOutput?.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
if session!.canAddOutput(stillImageOutput) {
session!.addOutput(stillImageOutput)
session!.startRunning()
}
}
}
}
func capture() -> UIImage {
var image: UIImage!
if let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo) {
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) -> Void in
if sampleBuffer != nil {
let cgImageRef = self.setBufferData(sampleBuffer: sampleBuffer!)
image = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right)
}
})
}
return image
}
func setBufferData(sampleBuffer: CMSampleBuffer) -> CGImage {
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)
let dataProvider = CGDataProvider(data: imageData as! CFData)
let cgImageRef = CGImage(jpegDataProviderSource: dataProvider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)
return cgImageRef!
}
}
:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
profilePhoto.startSession()
}
func capturePhoto() {
profileImage.image = profilePhoto.capture()
}
を
fatal error: unexpectedly found nil while unwrapping an Optional value
whe nはprofilePhoto.capture()で画像を返します。
私はセッションがiosに新しいものとして機能するのを理解していませんが、画像をキャプチャしようとするとセッションが終了しているので(?)どんな洞察も素晴らしいだろう。ありがとう
更新:私は十分に近いと答えたupvotes、以下は私のために働いたものです。
func capture(completion: @escaping (UIImage?) -> Void) {
if let videoConnection = stillImageOutput!.connection(withMediaType: AVMediaTypeVideo) {
stillImageOutput?.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (sampleBuffer, error) -> Void in
if sampleBuffer != nil {
let cgImageRef = self.setBufferData(sampleBuffer: sampleBuffer!)
let image: UIImage! = UIImage(cgImage: cgImageRef, scale: 1.0, orientation: UIImageOrientation.right)
completion(image)
} else {
completion(nil)
}
})
} else {
completion(nil)
}
}
メソッド名の状態に応じて、イメージは非同期にキャプチャされます。参照してください:http://stackoverflow.com/questions/31794542/ios-swift-function-that-returns-asynchronously-retrieved-value – dan
@ダン私は、あなたも提供した他のリンクを見て、私のコードにそれを適用する?別のヒントが大好きです。お返事ありがとう – Wazza