RAII的Objective-C模式?

Jör*_*son 4 raii objective-c exception-safety

我发现自己编写这样的代码来实现异常安全的代码:

Container* container = [Container new];
@try {
    while(someCondition) {
        ElementType* value = [someObject createObjectFromStorage];
        [container add:value]; // container retains object
        [value release];
    }

    [_container release];
    _container = [container retain];
} @finally {
    [container release];
}
Run Code Online (Sandbox Code Playgroud)

在Objective-C中还有其他一些更简洁的模式吗?

BJ *_*mer 8

如果你只是想确保你已经释放了你的物体,那就autorelease足够了.您还可以查看Xcode 4.2中的新自动引用计数选项.

一般而言,Objective-C不适用于RAII,因为所有Objective-C对象都在堆上分配.这意味着对象的生命周期没有显式地绑定到任何特定的堆栈帧,因此您不能依赖于在分配它的方法的末尾解除分配的对象.

您还应该知道Cocoa框架仅使用异常来指示程序员错误,而不是预期的错误条件.来自Apple的" 异常编程指南 "文档:

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

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

实际上,因为异常仅用于特殊情况,所以默认情况下,新引入的自动引用计数会在抛出异常时故意泄漏对象:

标准的Cocoa约定是异常信号编程器错误,并不打算从中恢复.默认情况下使代码异常安全会对通常实际上并不关心异常安全的代码施加严格的运行时和代码大小惩罚.因此,ARC生成的代码默认在异常时泄漏,如果过程将立即终止,这很好.关注从异常中恢复的程序应启用该选项.

如果你坚持使用该框架的习语,那么使用Cocoa框架进行编程会更好.这意味着仅对程序员错误使用异常并处理预期的运行时错误NSError.大多数Cocoa程序员从不担心编写异常安全的代码,因为他们的代码首先不会抛出异常.你可能会效仿.

  • 我来自C++背景,我必须说我发现Apple的异常方法有点"奇怪",温和地说.他们基本上说只要你"保留自己"就可以使用例外.我可以看到对异常进行最小化处理的原因,因为代码很快就会成为cludgy,因为RAII模式没有真正的机制.另一方面,代码可以变得相当笨拙,同时也一直在检查返回值......哦.新房子,新规则!:) (2认同)