brianadvent / CustomCamera

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Swift 4 has runtime errors with code

jld23 opened this issue · comments

commented

This is a great tutorial! I'm stuck on swift 4 syntax changes and I'm hoping you can help.

This line of code in ViewController prepareCamera function

if let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes:  [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices

Has a Buildtime error:

ViewController.swift:34:12: Initializer for conditional binding must have Optional type, not '[AVCaptureDevice]'

I've tried several things and this converted it from an Error to a Warning:

if let availableDevices = try?
            AVCaptureDevice.DiscoverySession(deviceTypes:  [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices
ViewController.swift:53:13: No calls to throwing functions occur within 'try' expression

This also happens with if let previewLayer in the beginSession function

I was having the same issue, you have to cast your variable in order for it to not have that issue. It looks like this:
if let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .back).devices as? [AVCaptureDevice]

Although this error still persists: Conditional cast from 'AVCaptureVideoPreviewLayer' to 'AVCaptureVideoPreviewLayer' always succeeds

Your code will still be able to build and run.

Using XCode Version 9.3.1 (9E501)

A similar (follow on) error occurs in the func beginSession ()
in the section:
if let previewLayer =

It seems to be related but I can't get it working! Any help would be appreciated

Initializer for conditional binding must have Optional type, not 'AVCaptureVideoPreviewLayer'

    if let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) {
        self.previewLayer = previewLayer
        self.view.layer.addSublayer(self.previewLayer)
        self.previewLayer.frame = self.view.layer.frame
        captureSession.startRunning()

I'm having the same problem with func beginSession() in Xcode 9.4

This setup is not ideal but works for the moment with 9.4.
There is certainly a way to make it work properly, but you can use the mods I made below to at least get past the critical stop and work on other parts of your app development.
So it fixed the problem but states:
Conditional cast from '[AVCaptureDevice]' to '[AVCaptureDevice]' always succeeds.
and
Conditional cast from 'AVCaptureVideoPreviewLayer' to 'AVCaptureVideoPreviewLayer' always succeeds.

Hope it helps!

func prepareCamera() {
    captureSession.sessionPreset = AVCaptureSession.Preset.photo
    
    if let availableDevices = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video,
// position: .back).devices as? [AVCaptureDevice]{
        position: .back).devices as? [AVCaptureDevice]{

        captureDevice = availableDevices.first
        beginSession()
    }
}

func beginSession () {
    do {
        let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
        
        captureSession.addInput(captureDeviceInput)
        
    }catch {
        print(error.localizedDescription)
    }
    
    
    if let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) as? AVCaptureVideoPreviewLayer {
        self.previewLayer = previewLayer
        self.view.layer.addSublayer(self.previewLayer)
        self.previewLayer.frame = self.view.layer.frame
        captureSession.startRunning()
        
        let dataOutput = AVCaptureVideoDataOutput()
        dataOutput.videoSettings = [(kCVPixelBufferPixelFormatTypeKey as NSString):NSNumber(value:kCVPixelFormatType_32BGRA)] as [String : Any]
        
        dataOutput.alwaysDiscardsLateVideoFrames = true
        if captureSession.canAddOutput(dataOutput) {
            captureSession.addOutput(dataOutput)
        }
        captureSession.commitConfiguration()
         let queue = DispatchQueue(label: "com.brianadvent.captureQueue")
        dataOutput.setSampleBufferDelegate(self, queue: queue)
    }
}

FWIW, I completed his tutorial and hosted my code here. If you're concerned about any modern Swift issues that have cropped up, you can consult my code to see how I got it to run: https://github.com/hawkins/XCodeSwiftCameraTutorial