iOS中异常处理的正确方法是什么?

5
我了解到,Objective-C 有一种与 C# 在 .NET 中处理异常相同的方式。此外,正如苹果文档所述,我想处理/处理异常,并创建一个 NSError 对象。仔细查看文档中“捕获不同类型的异常”部分 exception handling
我想要捕获不同类型的异常。在 .NET 中,我习惯于浏览类方法的文档以获取它可能引发的异常。从苹果文档中获取这些信息的位置在哪里?我如何知道 -method/object/process- 可能引发哪些类型的异常?
3个回答

5

在Objective-C世界中,错误处理可能与您所熟悉的方式大不相同。简而言之,请忘记异常。大多数错误都通过返回值或通过传递指向NSError*的指针来处理:

NSErrror *error = nil;
BOOL success = [somebody doSomethingWithError:&error];
if (!success) {
    NSLog(@"Got error: %@", error);
}

在被调用方的一侧:

- (BOOL) doSomethingWithError: (NSError**) error
{
    error = error ? error : &(NSError*){ nil };
    if (somethingWentWrong) {
        *error = [NSError …];
        return NO;
    }
    // All is fine
    return YES;
}

这看起来很繁琐,但在实践中它基本上还是有效的。在极少数情况下,某些东西确实会抛出异常(例如[NSFileHandle writeData:]),文档会提到这一点,但我认为你不需要像其他语言中那样分析异常。


嗨zoul,感谢您的回答。只是为了自己的安心->这意味着一个好的做法是在我的项目中所有代码周围构建一个try&catch块(以防我忘记正确处理某些内容-例如检查空值),以防止软件崩溃。否则,我可以继续开发而不必担心异常处理吗? -或者只需在我的主方法周围构建try和catch块,因为未处理的异常最终会到达那里(然后记录它或向用户显示消息) - Tom
在Objective-C中,“Null”对象的处理方式不同,向nil对象发送消息是合法的。这有时是一个很好的时间节省器,有时也是一个等待发生的漂亮的错误。在Objective-C中,您可以大多数情况下忘记try/catch块。每当您调用可能失败的内容时,请查看错误将如何返回。在大多数情况下,您将收到一个NSError,因此从方法签名中可以明显看出。在极少数剩余的情况下,文档会告诉您该方法可能会抛出异常,因此您需要在那里使用try/catch块。再次强调,这种情况很少见。 - zoul

5
正如苹果的文档所说,大多数异常是在异常情况下抛出的。(有些异常不是这样,比如访问NSArray边界之外的对象。)
.NET鼓励本地异常处理。Cocoa编写时鼓励使用大范围异常处理。在.NET中使用本地异常处理的原因是您期望某个部分以预期的方式失败(例如下载内容时出现网络错误)。在Cocoa中,通过使用返回NSErrors的方法来处理此类情况。这是一样的,只是在方法签名中更加可见。
一个好的经验法则是,Cocoa仅在情况不明确如何恢复时才会抛出异常。(不要将这误解为异常在.NET中无处不在且难以处理。)

2

请查看开发人员参考的异常处理。在Cocoa中,我们不会得到像nilArgumentException这样的异常,我们只会得到NSException。为了提供细粒度的消息或处理,您可以执行以下操作:

if ([[exception name] isEqualToString:MyAppException]) 

以下是在NSException头文件中定义的异常名称列表。
FOUNDATION_EXPORT NSString * const NSGenericException;
FOUNDATION_EXPORT NSString * const NSRangeException;
FOUNDATION_EXPORT NSString * const NSInvalidArgumentException;
FOUNDATION_EXPORT NSString * const NSInternalInconsistencyException;

FOUNDATION_EXPORT NSString * const NSMallocException;

FOUNDATION_EXPORT NSString * const NSObjectInaccessibleException;
FOUNDATION_EXPORT NSString * const NSObjectNotAvailableException;
FOUNDATION_EXPORT NSString * const NSDestinationInvalidException;

FOUNDATION_EXPORT NSString * const NSPortTimeoutException;
FOUNDATION_EXPORT NSString * const NSInvalidSendPortException;
FOUNDATION_EXPORT NSString * const NSInvalidReceivePortException;
FOUNDATION_EXPORT NSString * const NSPortSendException;
FOUNDATION_EXPORT NSString * const NSPortReceiveException;

FOUNDATION_EXPORT NSString * const NSOldStyleException;

更正:

如下面的评论所建议的那样,您可以对NSException类进行子类化,以捕获自定义异常。


1
没有什么可以阻止你从NSException派生子类,并在@catch块中捕获特定类型的异常,以供自己的代码使用。 - user23743
@GrahamLee。您说得非常正确。您肯定可以扩展功能。我也开始关注您的博客了 :) - Vignesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接