我正在致力于将 Java 代码库移植到 Cocoa/Objective-C,以便在桌面 Mac OS X 上使用。Java代码有 地段地段 带有检查异常的方法,例如:

double asNumber() throws FooException {
    ...
}

在 Objective-C 中表示这些的最佳方式是什么?异常或错误输出参数?

- (CGFloat)asNumber { 
    ... // possibly [FooException raise:format:];
}

或者

- (CGFloat)asNumberError:(NSError **)outError {
    ...
}

我感觉错误通常是 Objective-C 更好的解决方案,但正如你所看到的......很多像上面这样的方法看起来会很别扭。再说一次,还有 地段 这些。

当然请记住,因为这些是 检查过 Java 中的异常,我需要添加 @try 块或 if (*outError) {...} 检查这些方法被调用的地方(地段 的地方)。

我记得进去时听到 @try 块曾经在 Objective-C 中很昂贵,但在 64 位或 SL 或其他一些新环境中很便宜(记不清了)。我根本不关心向后兼容性,所以我 确实 只为新潮而设计。

有帮助吗?

解决方案

你应该 绝对避免异常 用于从字符串中解析数字之类的事情。在 Objective-C 中,异常代表程序员错误,而不是用户输入错误,甚至是不可用的文件。(部分原因是异常处理总是比更“传统”的错误处理成本更高、更复杂。不管事实如何 进入 @try 块在 64 位中是“零成本”, 当然,你可以随心所欲地使用异常,但这不是 Cocoa 的方式,而且你会发现自己与其他 Objective-C 代码不一致。使用你的代码的人会对你在本应导致错误的情况下抛出异常感到非常恼火。

苹果自己的文档:

“在许多环境中,异常的使用相当普遍。例如,您可能会抛出异常来表明例程无法正常执行,例如文件丢失或数据无法正确解析时。Objective-C 中的异常是资源密集型的。您不应将异常用于一般流程控制,或仅用于表示错误。相反,您应该使用方法或函数的返回值来指示发生了错误,并在错误对象中提供有关问题的信息。”

看看内置的 Cocoa 类如何处理这样的错误。例如, NS字符串 有类似的方法 -floatValue 如果失败则返回 0。针对您的特定情况的更好解决方案可能是 NS扫描仪 这样做,例如在 -scanFloat: — 接受指向应存储结果的字段的指针,并返回 YES 或者 NO 基于解析是否成功。

除了 Obejctive-C 约定和最佳实践之外,NSError 比 NSException 更加健壮和灵活,并且允许调用者根据需要有效地忽略问题。我建议通读 Cocoa 错误处理编程指南. 笔记: 如果您接受 NSError** param,我强烈建议你也设计成允许客户端通过 NULL 如果他们不想收到任何错误信息。我知道的每个 Cocoa 类都会针对错误执行此操作,包括 NSString。

尽管移植的代码最终可能看起来与 Java 代码完全不同,但要认识到它将由 Objective-C 代码使用,而不是由 Java 等效项的相同客户端使用。绝对符合该语言的习语。该端口不会是 Java 代码的镜像,但结果会更加正确(对于 Objective-C)。

其他提示

在可可,异常实际上只应该被用于“编程错误;”理念是让应用程序赶上他们,给用户节省了他们在做什么,并退出该选项。首先,不是所有的框架或代码路径可能是100%的异常安全,所以这可能是行动的唯一可靠的办法。对于可以预期,并从回收的错误,则应使用NSError,通常经由out参数。

你是正确的,“出错误通常是ObjC更好的解决方案。”很少会你发现可可抛出异常的API(除非你没有满足对API的先决条件,但在这种情况下,此行为被默认未定义)。

如果您希望这个代码活过你和其他Cocoa开发获得通过,我会建议使用了错误。我对那个被人们熟悉可可编译后的代码工作,谁宽松使用的例外,他们是一个皇家疼痛来解决。

我就是目标C使用超时错误的方法的一个大风扇。你必须处理异常,但你可以选择,如果你想忽略了错误。这一切都吻合了Objective-C的态度,即“程序员知道他们在做什么。”这也使得Objective-C的一个非常干净的前瞻性的语言,因为你的代码不使用try-catch块混乱。

这是说 - 你可能要考虑:是否有例外情形被忽略的任何方案?你扔真正异常的关键的?你是否发现自己写的清理变量,继续简单的catch块?我偎过去出错误,因为我喜欢只有最严重的错误语法和Objective-C储量异常。

它看起来像这些检查的异常更干净映射到了错误。异常仍然可以使用,但应保留用于特殊情况。

例外可能是最好的方法,因为64位的OBJ-C ABI时(runtime)使用零个成本例外,所以你没有真正的成本获得更清晰的代码。当然,在32位老了setjmp / longjmp的例外仍然在使用和不使用C ++进行交互,所以如果这是一个目标,那么你有问题。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top