我的一个朋友要求我不要在iPhone应用中使用NSexception。他给出的原因是“表演瓶颈”。但是我不相信这一点。

有人可以确认我应该克制iPhone应用中使用NSexception吗?如果您有使用NSexception的最佳实践,请也提供。

更新:

关联 请求我们在应用程序级别使用异常处理。有人做过吗?请给出它的优势以及它可能创建的任何其他性能障碍。

有帮助吗?

解决方案

简而言之:

请勿使用异常来指示任何内容,但无法恢复错误

仅使用 @try/ @catch来处理不可撤销的错误是合适的。使用@throw/@try/@catch绝不合适,例如在iOS或Mac OS X上进行操作。致电Abort());坠机通常留下更多的证据。

例如,除非您的目标是捕获它们并以某种方式报告错误,否则使用遇到的异常是不合适的处于不一致的状态,可能会丢失数据。

通过系统框架代码抛出的任何例外的行为均未定义。


您能否解释“通过系统框架代码抛出的任何例外的行为是不确定的”。详细地?

当然。

系统框架使用设计,其中任何例外都被认为是致命的,不可恢复的错误;程序员错误,出于所有意图和目的。该规则的例外数量非常有限。

因此,在其实施中,如果抛弃了通过系统框架代码的异常,则系统框架将无法确保一切都必须正确清理。从定义上讲,正弦的例外是为什么要支付清理费用?

考虑此通话堆栈:

your-code-1()
    system-code()
        your-code-2()

即代码在系统代码中调用代码,该代码将其调用到更多的代码中(尽管调用堆栈显然更深,但非常常见的模式)。

如果 your-code-2 引发例外,例外已经过去了 system-code 意味着行为不确定; system-code 可能会或可能不会将您的应用程序留在未定义的,可能崩溃或数据遗憾的状态中。

或者,更强烈:您不能在 your-code-2 期望您可以抓住并处理它 your-code-1.

其他提示

我已经使用了例外处理来进行密集 音频应用程序 没有任何问题。经过大量阅读和一些基准测试和拆卸分析之后,我得出了一个有争议的结论,没有真正的理由不使用它们(聪明地)和很多理由不使用(nserror指针,无穷无尽的条件... youck!)。人们在论坛上所说的大多数只是重复Apple文档。

我详细介绍了 这篇博客文章 但是我将在这里概述我的发现:

误解1:@try/@catch/@终于太贵了(就CPU而言)

在我的iPhone 4上,投掷和捕获100万个例外大约需要8.5秒。这相当于每个小微秒约8.5微秒。您的实时CoreAudio线程昂贵?也许有点(但是您永远不会抛出例外吗?

误解2:@Try Blocks在32位iOS上的费用

苹果文档说“零成本@try块 64位“并指出32位会产生成本。一些基准测试和拆卸分析似乎表明32位iOS(ARM处理器)上也有零成本@Try块。苹果的意思是说32bit 英特尔?

误解3:重要的是,通过可可框架抛出的例外是不确定的

是的,它们是“未定义的”,但是您在Apple框架上投掷什么? 当然 苹果不为您处理它们。 实现可回收错误的异常处理的全部要点是在本地处理它们 - 并非每个单行线“本地”。

这里的一个边缘情况是使用类似的方法 NSObject:performSelectorOnMainThread:waitUntilDone:. 。如果以后的参数是肯定的,那么这就像同步函数,在这种情况下,您可能会因为期望异常而闻到呼叫范围而被原谅。例如:

/////////////////////////////////////////////////////////////////////////
#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;
}
// ...

在这种情况下,例外将通过“通过可可框架”(主线程的运行循环)错过了您的捕获和崩溃。您可以使用GCD轻松解决此问题 dispatch_synch 并放入它的块参数,方法调用以及任何异常处理。

为什么要在nserror上使用nsexception

任何曾经在基于C的旧框架之一(例如Core Audio)中完成工作的任何人都知道它正在检查,处理和报告错误。主要好处 @try/ @catch和nSexceptions提供的是使您的代码更清洁且易于维护。

假设您有5行代码,可以在文件上使用。每个都可能会丢弃3个不同的错误(例如,磁盘空间,读取错误等)。与其将每行的条件包装在任何条件下检查无返回值,然后将NSERROR指针调查外包给另一种OBJC方法(或更糟糕的是,使用 #define 宏!),您将所有5行包裹在 一个 @Try并在那里处理每个错误。考虑一下您将保存的行!

通过创建NSexception子类,您还可以轻松地集中错误消息,并避免将代码乱扔。您还可以轻松地将应用程序的“非致命”例外区分开,并将其与致命程序员错误(如NSASSERT)区分开。您还可以避免需要“名称”常数(子类的名称为“名称”)。

所有这些示例以及有关基准和拆卸的更多详细信息是 在此博客文章中...

异常加尝试/捕获/最后是几乎所有其他主要语言(C ++,Java,PHP,Ruby,Python)使用的范式。也许是时候放下偏执狂并拥抱它……至少在iOS中。

通常问自己是要发出错误的信号,还是实际上有特殊情况?如果前者,那么无论出现任何表现问题,这都是一个非常糟糕的主意。如果后者,这绝对是正确的事情。

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