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

时间:2016-02-11 05:21:07

标签: ios swift2 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

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

我错过了什么?

更新:From Apple's documentation on AVAudioFile

有关:

func readIntoBuffer(_ buffer: AVAudioPCMBuffer) throws

讨论:

  

处理SWIFT中的错误:

     

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

     

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

来自The Swift Programming Language (Swift 2.1): Error Handline

  

请注意

     

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

最后,来自同一份文件:

  

使用Do-Catch处理错误

     

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

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

3 个答案:

答案 0 :(得分:4)

do - catch组合没问题。这个问题只是一个无法捕获的问题 - 因此永远不会进入catch阻止。

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

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

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

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

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

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

答案 1 :(得分:2)

catch只会捕获显式抛出的错误。它永远不会捕获异常。

你在这里看到的是AVAudioFile SDK中发生的异常,而不是Swift错误,所以它没有被捕获:

  

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

在Swift的上下文中,“error”表示函数抛出的错误,没有别的。你的功能与否无关紧要。

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

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

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

答案 2 :(得分:0)

见这个例子

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