我的一位朋友问我不要在iPhone应用程序中使用NSException。他给出的原因是“性能瓶颈”。但我不相信它。在iPhone应用程序中使用NSException
有人可以确认我们应该禁止在iPhone应用程序中使用NSException吗?如果您有使用NSException的最佳实践,请提供。
UPDATE:
这link要求我们在应用级使用异常处理。有人曾经做过吗?请说明它的优点以及它可能产生的其他任何表现。
我的一位朋友问我不要在iPhone应用程序中使用NSException。他给出的原因是“性能瓶颈”。但我不相信它。在iPhone应用程序中使用NSException
有人可以确认我们应该禁止在iPhone应用程序中使用NSException吗?如果您有使用NSException的最佳实践,请提供。
UPDATE:
这link要求我们在应用级使用异常处理。有人曾经做过吗?请说明它的优点以及它可能产生的其他任何表现。
简而言之:
只有适合使用@尝试/ @赶上来处理不可恢复的错误。使用@ throw/@ try/@ catch在iOS或Mac OS X上执行类似操作的控制流是绝对不合适的。即便如此,请仔细考虑是否最好使用异常来指示不可恢复的错误或仅仅是崩溃(调用abort());事故经常会留下更多的证据。
例如,除非您的目标是捕捉它们并以某种方式报告错误,否则 - 通常 - 崩溃或至少警告该错误,否则它不适合用于捕获越界异常用户表示您的应用处于不一致状态,并可能会丢失数据。
通过系统框架代码抛出的任何异常的行为是未定义的。
你能解释一下“通过系统 框架代码是未定义的抛出的任何异常 行为。”在 的详细资料?
当然。
系统框架使用一种设计,其中任何异常被认为是致命的,不可恢复的错误;一个程序员错误,为所有意图和目的。这条规则的例外(heh)数量非常有限。
因此,在它们的实现中,如果通过系统框架代码抛出异常,系统框架将不能确保一切都必须正确地清理干净。根据定义,正常情况下,例外是不可恢复的,为什么要支付清理费用?
考虑这个调用堆栈:
your-code-1()
system-code()
your-code-2()
即代码将代码调用到调用更多代码的系统代码中(一种非常常见的模式,尽管调用堆栈明显更深)。
如果your-code-2
引发异常,异常通过system-code
表示行为未定义; system-code
可能会或可能不会让您的应用程序处于未定义的,潜在的崩溃或数据有损状态。
或者更为强烈:您不能在your-code-2
中抛出异常,期望您可以在your-code-1
中捕捉并处理它。
我使用异常处理我相当密集的audio app没有任何问题。经过多次阅读和一些基准测试和反汇编分析后,我发现了一个有争议的结论:没有真正的理由不使用它们(智能地)并且没有足够的理由(NSError指针指针,无尽条件...呸!)。大多数人在论坛上发表的意见都是重复Apple Docs。
我去到相当多的细节,在this blog post,但我会在这里勾勒出我的发现:
在我的iPhone 4上,抛出和捕捉100万个异常大约需要8.5秒。这相当于每个只有大约8.5微秒。在实时CoreAudio线程中价格昂贵?也许有点(但你永远不会抛出异常吗?),但UIAlert的8.5μs延迟告诉用户打开文件时出现问题,是否会被注意到?
苹果的文档“上零成本@try块”和国家的说出32位招致成本。小小的基准测试和反汇编分析似乎表明,在32位iOS(ARM处理器)上也有零成本的@try块。苹果的意思是说32bit 英特尔?
是的,他们是“不确定”,但你在干什么通过苹果框架扔呢? 当然苹果不会为你处理它们。 实现可恢复错误异常处理的重点是在本地处理它们,而不是在本地“单线”处理。
这里的一个边缘案例是与像NSObject:performSelectorOnMainThread:waitUntilDone:
一样的方法。如果后面的参数是YES,这就像是一个同步函数,在这种情况下,您可能会被原谅,因为期望异常会向您的调用范围发送。例如:
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCThread
/////////////////////////////////////////////////////////////////////////
@interface l5CCThread : NSThread @end
@implementation l5CCThread
- (void)main
{
@try {
[self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES];
} @catch (NSException *e) {
NSLog(@"Exception caught!");
}
}
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; }
@end
/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCAppDelegate
/////////////////////////////////////////////////////////////////////////
@implementation l5CCAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
l5CCThread *thd = [[l5CCThread alloc] init];
[thd start];
return YES;
}
// ...
在这种情况下,除了将通过“通过Cocoa框架”(主线程的run loop)缺少你捕捉和崩溃。您可以使用GCD的dispatch_synch
轻松解决此问题,并将方法调用加上其块参数加上任何异常处理。
任何人都知道什么是苦差事它是检查,处理和报告错误。 @ try/@ catch和NSExceptions提供的主要好处是让你的代码更简洁,更易于维护。
假设你有5行代码在文件上工作。每个可能会抛出一个,比如3个不同的错误(例如,磁盘空间不足,读取错误等)。不是将每行都包含在检查NO返回值的条件中,而是将NSError指针调查外包给另一个ObjC方法(或者更糟糕的是,使用的宏是#define
!),则将所有5行全部包含在 @try中,并将其包装为 @try在那里处理每个错误。想想你会省下的路线!
通过创建NSException子类,您还可以轻松集中错误消息,并避免您的代码与他们散落在一起。您还可以轻松区分应用程序的“非致命”异常与致命程序员错误(如NSAssert)。您也可以避免使用“name”常量(子类的名称,即“名称”)。关于基准和拆卸的这一切
例子和更多的细节是on this blog post ...
例外加的try/catch /最后是(C++,Java,PHP和通过几乎使用所有其他主要语言范式, Ruby,Python)。也许是时候放弃这种偏执狂了,至少在iOS中也是如此。
你能解释一下:“通过系统框架代码抛出的任何异常的行为是未定义的。”详细? – Krishnan 2010-11-30 08:35:54