Objective-C例外

Adr*_*ith 52 exception-handling objective-c nserror

我刚刚完成了一个iPhone应用程序编程课程.作为课程的一部分,我看到了

  • Objective-C使用该@try指令提供异常处理
  • 系统库不使用异常处理,而不喜欢 return nil

我问我是否应该对我编写的新代码使用异常处理(例如,如果我同时编写前端和逻辑代码,那么它们之间的通信就在我手中)但是我被告知不,我不应该使用新的异常码.(但他没有详细说明,然后课程继续进行,我想也许后来原因会变得清晰......)

当然例外优于return nil?你可以捕获特定的类型,你不要忽略通常成功的函数的返回类型来忽略它们,你有可以记录的文本消息,它们允许你的代码专注于正常情况,因此更具可读性.为什么要使用例外.

所以你怎么看?我的教练是不是不使用Objective-C例外?如果是这样,为什么?

zne*_*eak 65

在没有自动管理资源的情况下抛出异常是不安全的.这是Cocoa框架(和邻居框架)的情况,因为它们使用手动引用计数.

如果抛出异常,则release通过展开堆栈而跳过的任何调用都将导致泄漏.只有当您确定不会恢复时,这应该限制您的时间,因为当进程退出时,所有资源都会返回到操作系统.

不幸的是,NSRunLoops倾向于捕获传播给它们的所有异常,所以如果你在事件期间抛出,你将恢复到下一个事件.这显然是非常糟糕的.因此,你最好不要扔掉.

如果使用垃圾收集的Objective-C,则会减少此问题,因为将正确释放由Objective-C对象表示的任何资源.但是,malloc未包含在Objective-C对象中的C资源(例如文件描述符或已分配的内存)仍将泄漏.

所以,总而言之,不要扔掉.

正如您所提到的,Cocoa API有几种解决方法.返回nilNSError**模式是其中两个.

澄清ARC

ARC用户可以选择启用或禁用完全异常安全性.启用异常安全时,ARC将生成代码以在其作用域被终止时释放强引用,从而可以安全地在代码中使用异常.ARC不会修补外部库以在其中启用异常支持,因此即使在程序中启用了异常支持,也应该小心抛出(尤其是捕获的位置).

可以启用-fobjc-arc-exceptions或禁用ARC异常支持-fno-objc-arc-exceptions.默认情况下,它在Objective-C中禁用,但在Objective-C++中启用.

默认情况下,Objective-C中的完全异常安全性被禁用,因为Clang作者认为Objective-C程序无法从异常中恢复,并且因为代码大小成本较高且与该清理相关的性能损失较小.另一方面,在Objective-C++中,C++已经引入了大量的清理代码,人们实际上更需要异常安全.

这些都来自LLVM网站上的ARC规范.

  • @Adrian Smith在`@ finally`中发布你自己的方法很好.但是,如果方法中的异常传播给它们,那么调用你的方法可能会或者可能不会有`@ finally`块来清理. (3认同)
  • 实际上问题并没有随GC消失.除了内存之外还有其他资源需要发布. (3认同)
  • 如何释放对象@finally块?(或者这太不优雅了,导致代码过多?) (2认同)

bbu*_*bum 34

在Cocoa和iOS编程中,异常用于指示不可恢复的程序员错误.当框架抛出异常时,它表明框架已检测到一个既不可恢复又且内部状态现在未定义的错误状态.

同样,通过框架代码抛出的异常会使框架处于未定义状态.即你不能做这样的事情:

void a() {
    @throw [MyException exceptionWithName: @"OhNoes!"  ....];
}

@try {
    ... call into framework code that calls a() above ...
} @catch (MyException e) {
    ... handle e ...
}
Run Code Online (Sandbox Code Playgroud)

底线:

Cocoa中不会使用异常进行流量控制,用户输入验证,数据有效性检测或以其他方式指示可恢复的错误.为此,您使用此处记录NSError**模式(感谢Abizem).

(请注意,有少量API违反此规定 - 其中使用异常来表示可恢复状态.已针对这些异常提交错误以弃用并最终消除这些不一致.)


终于找到了我要找的文件:

要点:您应该保留使用异常进行编程或意外的运行时错误,例如越界收集访问,尝试改变不可变对象,发送无效消息以及丢失与窗口服务器的连接.在创建应用程序时而不是在运行时,通常会使用异常处理这些类型的错误.

如果您有一个使用异常来处理错误条件的现有代码体(例如第三方库),则可以在Cocoa应用程序中按原样使用代码.但是,您应该确保任何预期的运行时异常都不会从这些子系统中逃脱,最终会出现在调用者的代码中.例如,解析库可能在内部使用异常来指示问题,并允许快速退出可能深度递归的解析状态; 但是,您应该注意在库的顶层捕获此类异常,并将它们转换为适当的返回代码或状态.


Abi*_*ern 7

我认为,如果我错了,其他人会纠正我,应该使用异常来捕获程序员错误,而NSError类型错误处理应该用于程序运行时发生的异常情况.

至于返回nil,这不是全部 - 可能有问题的函数不只是返回a nil,它们也可以(并且应该)使用作为参数传入的NSError对象提供更多信息.

也可以看看