9

スロー可能な呼び出しが必要なdispatch_asyncを使用しようとしていますが、Swiftの新しいエラー処理とメソッド呼び出しが私を混乱させています。

コード:

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)
        }
    }
}

警告:

: タイプ '() throws -> _' のスロー関数から非スロー関数タイプ '@convention(block) () -> Void' への無効な変換

4

1 に答える 1

11

最終編集: このバグは Swift 2.0 最終版 (Xcode 7 最終版) で修正されています。

変化する

} catch let error as NSError {

} catch {

効果はまったく同じです — それでもできますprint(error)— しかし、コードはコンパイルされ、あなたは道を進んでいきます.

編集これが、(コメントで述べたように)あなたが見つけたのはバグだと思う理由です。これはうまくコンパイルされます:

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

コンパイラは文句を言わず、特に書き込みを強制しません— したがって、コンパイラがこれが網羅的func test() throwsであると考えていることを証明しています。catch

しかし、これはコンパイルされません:

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

しかし、それはまったく同じdo/catchブロックです!では、なぜここでコンパイルしないのでしょうか? コンパイラが周囲の GCD ブロックによって何らかの形で混乱しているためだと思います(したがって、@convention(block)関数に関するエラーメッセージのすべてのもの)。

したがって、私が言いたいのは、両方ともコンパイルするか、両方ともコンパイルに失敗するかのどちらかです。一方がそうで他方がそうでないという事実は、コンパイラのバグだと思います。私はまさにその根拠に基づいてバグレポートを提出しました。

EDIT 2:バグを説明する別のペアを次に示します(これは@fqdnのコメントからのものです)。これはコンパイルされません:

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

        }
    }
}

しかし、これまったく同じものですが、コンパイルされます:

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

        }
    }
    dispatch_async(dispatch_get_main_queue(), inner)
}

その矛盾がバグです。

于 2015-07-28T01:50:20.197 に答える