Swift 2.1 do-try-catch没有捕获错误

这是我的Swift 2.1代码片段。 发生错误的位置出现错误时显示的错误。

错误显示在调试面板中,应用程序崩溃。 该应用程序永远不会在捕获中打印该行,也不会按预期正常返回。

let audioFileURL = receivedAudio.filePathURL guard let audioFile = try? AVAudioFile(forReading: audioFileURL) else { print("file setup failed") return } let audioFileFrameCount = AVAudioFrameCount(audioFile.length) audioFileBuffer = AVAudioPCMBuffer(PCMFormat: audioFile.fileFormat, frameCapacity: audioFileFrameCount) do { // ERROR: AVAudioFile.mm:263: -[AVAudioFile readIntoBuffer:frameCount:error:]: error -50 // Terminating app due to uncaught exception 'com.apple.coreaudio.avfaudio', reason: 'error -50' // -50 = Core Audio: bad param try audioFile.readIntoBuffer(audioFileBuffer) } catch { print("unable to load sound file into buffer") return } 

从我看过的所有内容来看,我的do / try / catch格式应该是正确的。

audioFile.readIntoBuffer返回void并具有关键字throws

然而,捕获永远不会被执行。

我错过了什么?

更新: 来自Apple的AVAudioFile文档

对于:

 func readIntoBuffer(_ buffer: AVAudioPCMBuffer) throws 

讨论中:

处理SWIFT中的错误:

在Swift中,此API作为初始化程序导入,并使用throws关键字标记,以指示在出现故障时它会引发错误。

您可以在try表达式中调用此方法并处理do语句的catch子句中的任何错误,如Swift编程语言中的error handling(Swift 2.1)和使用Swift与Cocoa和Objective-C中的error handling(Swift 2.1)中所述)。

来自Swift编程语言(Swift 2.1):错误说明

注意

Swift中的error handling类似于使用try,catch和throw关键字在其他语言中的exception处理。 与许多语言中的exception处理不同 – 包括Swift中的Objective-Cerror handling不涉及展开调用堆栈,这个过程可能在计算上很昂贵。 因此,throw语句的性能特征与return语句的性能特征相当。

最后,来自同一份文件:

使用Do-Catch处理错误

您可以使用do-catch语句通过运行代码块来处理错误。 如果do子句中的代码抛出错误,则会与catch子句进行匹配,以确定哪一个可以处理错误。

我没有必要编写并抛出我自己的错误/exception才能被捕获。 我也应该能够捕获Swift的例外情况。

do - catch组合很好。 这个问题只是一个无法捕获的问题 – 因此永远不会进入catch块。

如果问题是可捕获的(通过Swift的throwsfunction定义和处理), catch块将被执行。


一些语义:关于术语错误exception之间的差异存在长期争论。

一些开发人员认为这两个术语是截然不同的。 在这种情况下,术语错误表示旨在处理的问题。 斯威夫特的throws动作适合这里。 在这种情况下, do - catch组合将允许捕获问题。

对于这些开发人员来说,一个例外是一个意外的,通常是致命的问题,无法捕获和处理。 (一般来说,即使你能抓住它,你也无法处理它。)

其他人认为这两个术语是等同的和可互换的,无论有关问题是否可以被捕获。 (Apple的文档似乎遵循这一理念。)

(更新以关注答案而不是语义。)

catch只会捕获明确抛出的错误。 它永远不会捕获exception。

你在这里看到的是AVAudioFile SDK中发生的exception,而不是Swift错误,因此它没有被捕获:

错误:AVAudioFile.mm:263: – [AVAudioFile readIntoBuffer:frameCount:error:]:error -50
因未捕获的exception“com.apple.coreaudio.avfaudio”而终止应用程序,原因:’error -50′
-50 =核心音频:糟糕的参数

在Swift的上下文中,“错误”表示函数抛出的错误,没有别的。 你的function与否并不重要。

斯威夫特的例外并没有被抓住。 例如,它与Java完全不同。 在Swift中,错误!=exception,它们是两个非常不同的东西。

我理解你的意见“它应该适用于两者”,但事实并非如此。 如果需要,您可以将此视为使用关键字“catch”的语义情况,因为它与其他语言的关键字相同,但行为却截然不同; 它很像,但它不一样。

至于你的AVAudioFile exception ,我没有解决方案 – 也许这是这个SDK中的一个错误? 或者它还没有正确绑定到Swift和投掷系统。 在这种情况下,如果没有其他人有解决方案,请不要犹豫向Apple报告错误。

看这个例子

 struct E: ErrorType{} func foo(i: Int) throws { if i == 0 { throw E() } print(10 / (i - 1)) } do { //try foo(1) // if you uncomment this line, the execution // will crash, even though the function is declared // as throwing and you use proper calling style (do / try / catch pattern) try foo(0) } catch { print("error: ", error) // error: E() }