Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dispatch_async() with throwables swift 2 Xcode 7

Trying to use dispatch_async in which i need a throwable call, but Swift's new error handling, and method calls are confusing me, if anyone could show me how to do this correctly, or point me in the right direction, I would greatly appreciate it.

Code:

func focusAndExposeAtPoint(point: CGPoint) {
    dispatch_async(sessionQueue) {
        var device: AVCaptureDevice = self.videoDeviceInput.device

        do {

            try device.lockForConfiguration()
            if device.focusPointOfInterestSupported && device.isFocusModeSupported(AVCaptureFocusMode.AutoFocus) {
                device.focusPointOfInterest = point
                device.focusMode = AVCaptureFocusMode.AutoFocus
            }

            if device.exposurePointOfInterestSupported && device.isExposureModeSupported(AVCaptureExposureMode.AutoExpose) {
                device.exposurePointOfInterest = point
                device.exposureMode = AVCaptureExposureMode.AutoExpose
            }

            device.unlockForConfiguration()
        } catch let error as NSError {
            print(error)
        }
    }
}

Warning:

: Invalid conversion from throwing function of type '() throws -> _' to non-throwing function type '@convention(block) () -> Void'

like image 676
justin shores Avatar asked Jul 28 '15 01:07

justin shores


1 Answers

FINAL EDIT: This bug is fixed in Swift 2.0 final (Xcode 7 final).

Change

} catch let error as NSError {

to

} catch {

The effect is exactly the same — you can still print(error) — but the code will compile and you'll be on your way.

EDIT Here's why I think (as I said in a comment) that what you've found is a bug. This compiles just fine:

func test() {
    do {
        throw NSError(domain: "howdy", code: 1, userInfo:nil)
    } catch let error as NSError {
        print(error)
    }
}

The compiler does not complain, and in particular does not force you to write func test() throws — thus proving that the compiler thinks this catch is exhaustive.

But this does not compile:

func test() {
    dispatch_async(dispatch_get_main_queue()) {
        do {
            throw NSError(domain: "howdy", code: 1, userInfo:nil)
        } catch let error as NSError {
            print(error)
        }
    }
}

But it's the exact same do/catch blocks! So why doesn't it compile here? I think it's because the compiler is somehow confused by the surrounding GCD block (hence all the stuff in the error message about the @convention(block) function).

So, what I'm saying is, either they should both compile or they should both fail to compile. The fact that one does and the other doesn't is, I think, a bug in the compiler, and I have submitted a bug report on precisely that basis.

EDIT 2: Here's another pair that illustrates the bug (this comes from @fqdn's comment). This does not compile:

func test() {
    dispatch_async(dispatch_get_main_queue()) {
        do {
            throw NSError(domain: "howdy", code: 1, userInfo:nil)
        } catch is NSError {

        }
    }
}

But this does compile even though it is exactly the same thing:

func test() {
    func inner() {
        do {
            throw NSError(domain: "howdy", code: 1, userInfo:nil)
        } catch is NSError {

        }
    }
    dispatch_async(dispatch_get_main_queue(), inner)
}

That inconsistency is the bug.

like image 79
matt Avatar answered Oct 26 '22 03:10

matt