在一个 @try-@catch-@finally 块中,是使用 finally 还是正常继续执行好呢?

13 浏览
0 Comments

在一个 @try-@catch-@finally 块中,是使用 finally 还是正常继续执行好呢?

这是一个简单的Objective-C问题。\n当你使用@try时,工作流程可以以两种方式运行:\n

    \n

  • 如果出现某些NSException,代码会立即跳转到@catch块,然后到@finally块。
  • \n

  • 如果没有出现异常,完成运行@try块,然后运行@finally块。
  • \n

\n那么,使用或者不使用@finally块有什么区别?如果我只使用:\n

-(void)function{
    @try {
     ...
    }
    @catch (NSException *exception) {
     ...
    }
    >>>无论如何,工作流程都将运行这一行?
}

\n然后剩余的函数将继续运行,或者只有在创建了NSException时才运行@catch块?

0
0 Comments

在一个@try-@catch-@finally块中,使用finally还是正常继续执行的问题的出现原因是因为Apple不推荐在生产代码中使用try/catch语句,因为它们会带来很高的代价,而实际的好处却很少。在C++中,防御性代码随处可见,可以设计应用程序为“基于异常”,这意味着所有代码都设计为堆栈回滚和抛出和重新抛出异常,直到它们达到堆栈的顶层。但是,在Obj-C中并非如此,在C++中,这种范式会破坏大多数编译器优化,因为编译器无法简化任何场景,因为异常可能会在中间中断它。

然而,Apple在Obj-C中提供了try/catch/finally机制,因此您可以创建仅在调试配置中才存在的代码,这将帮助您在将应用程序发布给公众之前发现和捕获错误。

此外,Apple还提供了完整(而美观)的“错误处理”范式和协议,支持API(NSError对象,嵌套的NSErrors NSError恢复协议,NSError显示API等),适用于在应用程序的“发布”版本中处理运行时错误。

所以,关于在生产代码中使用try/catch的整个讨论有点夸大其词。

这是误导性的。在Objective-C中,确实有一些API需要使用try/catch,其中最大的一个是NSTask,如果你哪怕稍微看一眼它,它就会引发一个异常。在某些情况下,某些API不采用传统的NSError方法,这种情况下,您不应该犹豫地使用try/catch来处理Apple的异常类。

因此,根据上述内容,我们可以得出结论,在生产代码中,不推荐使用try/catch语句,而是使用Apple提供的完整的错误处理范式和协议来处理运行时错误。但是,在调试配置中,可以使用try/catch/finally机制来捕获和调试错误。

0
0 Comments

在一个@try-@catch-@finally块中,使用finally还是正常继续执行,有以下几个要点需要注意:

1. finally块是可选的,可以用来执行无论是否发生异常都必须执行的操作,比如清理。

2. catch块不一定要捕获NSException,可以改为捕获更具体的异常。在这种情况下,finally块和catch块下方的代码将根据异常是否发生而决定是否执行。

3. catch块可以选择处理异常并重新抛出异常或者抛出不同的异常。换句话说,finally块将始终执行,无论catch块中做了什么。

4. 在iOS或Mac OS X开发中,将异常用作可恢复错误是违反系统规范的。如果异常通过系统框架代码的帧抛出,其行为是未定义的。因此,不要使用异常来管理可恢复的错误。

5. 在ARC下,异常默认情况下被编译器认为是不可恢复的。抛出异常(尽管没有进入@catch块)也会导致性能下降。

对于问题的出现原因,可以总结为:

- finally块的作用是在无论是否发生异常的情况下都执行一些必要的操作,比如资源的释放。

- catch块的作用是捕获异常并处理,可以选择重新抛出异常或者抛出不同的异常。

- 异常在iOS或Mac OS X开发中不应用于管理可恢复的错误,使用NSError模式来表示成功或失败。

解决方法如下:

- 对于必须执行的操作,可以将其放在finally块中。

- 对于特定的异常,可以使用更具体的异常类型来捕获。

- 对于可恢复的错误,应使用NSError模式来表示。

以下是整理后的文章:

在一个@try-@catch-@finally块中,我们可以选择使用finally块来执行一些必须在无论是否发生异常的情况下都执行的操作,比如资源的释放。catch块用于捕获异常并进行处理,我们可以选择重新抛出异常或者抛出不同的异常。

需要注意的是,catch块不一定要捕获NSException,我们可以根据具体情况选择更具体的异常类型。然而,无论我们在catch块中做了什么,finally块始终会执行。

另外,需要注意的是,在iOS或Mac OS X开发中,将异常用作可恢复错误是违反系统规范的。如果异常通过系统框架代码的帧抛出,其行为是未定义的。因此,我们不应该使用异常来管理可恢复的错误。

在ARC下,异常默认情况下被编译器认为是不可恢复的。抛出异常(尽管没有进入@catch块)也会导致性能下降。

总结起来,我们应该将必须执行的操作放在finally块中,选择更具体的异常类型来捕获异常,并使用NSError模式来表示可恢复的错误。

需要注意的是,在Mac OS X应用程序中,如果加载插件时发生异常,我们应该如何处理?应用程序应该退出还是尝试恢复?我们可以在插件加载的代码周围使用try-catch块,但是根据系统规范,不应该使用异常来管理可恢复的错误。因此,我们应该使用NSError模式来表示成功或失败。

总之,在@try-@catch-@finally块中,我们可以选择使用finally块来执行一些必须执行的操作,catch块用于捕获异常并进行处理。然而,在iOS或Mac OS X开发中,我们应该避免使用异常来管理可恢复的错误,而应使用NSError模式来表示成功或失败。

0
0 Comments

在一个@try-@catch-@finally块中,是否使用finally或者正常继续执行,这个问题的出现是因为finally块存在的目的是释放/清理资源,比如打开的套接字、打开的文件、数据库锁、信号量锁等等。如果在catch块内部发生错误或者catch块重新抛出异常,那么行:

>>>The workflow will run this line in any case?

将不会被执行。然而,finally块中的代码应该被执行。finally块是从即将崩溃的应用程序中干净地退出的最后、最好的机会。即使应用程序不会崩溃,它仍然是清理资源的最佳位置,因为与finally块内的代码相比,finally块外的代码更有可能在意外情况下被执行。

是的,在任何try/catch方案中,finally的目的是执行总是需要执行的代码,无论是否发生异常。在Objective-C中,可能是释放对象,在其他上下文中,可能是释放锁或关闭文件。

0