flashspys
flashspys

Reputation: 884

Var init in do-catch

Following code:

// Setup components
do {
    let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    let deviceInput   = try AVCaptureDeviceInput(device: captureDevice)
    let output        = AVCaptureMetadataOutput()
    let session       = AVCaptureSession()
} catch {
    return false
}

After this you can't access the initialized variables. The error is "Use of unresolved identifier" if I want to access e.g. deviceInput. But why? Either AVCaptureDeviceInput() crashes and the catch-Block returns or all is right and the variables are successfully initialized. What's the best solution to solve this ?

Upvotes: 1

Views: 1714

Answers (2)

matt
matt

Reputation: 535557

Vacawama's answer is perfectly correct, but just for educational purposes, here's a simplified version. You don't need anything but the initialization of deviceInput to happen inside a do block:

func test() {
    let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    let deviceInput : AVCaptureDeviceInput
    do { deviceInput = try AVCaptureDeviceInput(device: captureDevice) } catch {return}
    let output = AVCaptureMetadataOutput()
    let session  = AVCaptureSession()
    // ... other stuff here
    print("got to here")
}

If the try fails, "got to here" never prints; we have exited the function in good order.

Still another approach might be to let your surrounding function throw and just go for it, with no do...catch at all:

func test() throws {
    let captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    let deviceInput = try AVCaptureDeviceInput(device: captureDevice)
    let output = AVCaptureMetadataOutput()
    let session = AVCaptureSession()
    // ... other stuff here
    print("got to here")
}

This moves the onus of error-checking onto the caller of test().

Upvotes: 5

vacawama
vacawama

Reputation: 154631

The do block defines a new scope. If you declare the variables with let or var inside of the do {}, then they are only accessible within that block. If you want to use them after the do {}, then declare them before the do statement. Note, that you don't have to give them initial values, even if they are declared with let because you will only be setting them once before using them:

func foo() -> Bool {
    // Setup components
    let deviceInput: AVCaptureDeviceInput
    let captureDevice: AVCaptureDevice
    let output: AVCaptureMetadataOutput
    let session: AVCaptureSession

    do {
        captureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        deviceInput   = try AVCaptureDeviceInput(device: captureDevice)
        output        = AVCaptureMetadataOutput()
        session       = AVCaptureSession()
    } catch {
        return false
    }

    // Do something to demo that the variables are accessible
    print(deviceInput.description)
    print(output.description)
    print(session.description)

    return false
}

Upvotes: 5

Related Questions