iPhone开发:如何在Objective-C中捕获异常/ NSError?

9 iphone memory-management exception objective-c

我希望我的应用程序永远不会愚蠢地崩溃.我知道代码质量是解决此问题的根本原因.但是我仍然需要一个应用程序,以便在发生意外错误时永不崩溃.这是我想要尝试的代码.

-(void)testException
{
    @try
    {
        NSString* str;
        [str release];
    }
    @catch(NSException* ex)
    {
        NSLog(@"Bug captured");
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道这个不起作用.因为release从不提出例外.这是我的问题:

  1. 如何达到这种目标,将捕获bug,不会崩溃?
  2. 我如何知道哪个系统库会引发异常,因此我可以编写一些代码并知道它有效?

这是我读过的

  • 一个.Cocoa的异常编程主题
  • 湾 错误处理
    Cocoa 编程指南

我来自一个经验丰富的Microsoft程序员背景,其中catch异常或意外异常总是阻止我的程序在非常糟糕的环境中崩溃.

你们/ gals(Mac天才程序员)是如何制作无崩溃程序的?分享您的经验.

小智 12

Objective-C是一个非托管运行时; 您编译的代码直接在CPU上运行,而不是在虚拟机中运行.这意味着您没有可以像在.NET VM或JVM中运行时那样捕获每种可能的故障模式的监控层.它的长短是你要完全确定程序不会崩溃的唯一方法是非常仔细地编码并进行非常彻底的测试.即便如此,你也不确定,你只是认为你是.

最新版本的Xcode集成了Clang静态分析器("构建"菜单中的"构建和分析"),可以识别某些类别的潜在错误 - 我相当确定它会标记上面的例子.但这里没有灵丹妙药; 唯一的解决方案就是努力工作.


Cor*_*oyd 3

您遇到的一个问题是 str 从未初始化,这意味着 str 可能指向 nil (但这并不能保证)。它肯定指向垃圾。

如果你单步执行你的代码,我几乎可以保证你的版本是在 nil 上调用的,这在 Objective-C 中是完全有效的。

尝试这样做:

NSString *str = [[NSString alloc] initWithString:@"a string"];
[str release];
[str release];
Run Code Online (Sandbox Code Playgroud)

调用release不会释放对象,它只是将保留计数减1。当对象保留计数为0时,

[self dealloc];
Run Code Online (Sandbox Code Playgroud)

被自动调用。

如果上面的代码没有立即抛出异常,可能是因为实际的释放消息在将来的某个时刻被延迟(我不确定在保留计数达到 0 之后调用 dealloc 的确切时间。我认为是立即调用的,并且在同一个线程上,但其他一些可可忍者肯定会知道)。

您可以做的就是向 NSObject 添加一个类别并实现 dealloc 和 release 方法,并尝试捕获其中的异常。

- (void)dealloc{

 @try
    {
        [super dealloc];
    }
 @catch(NSException* ex)
    {
        NSLog(@"Bug captured");
    }

}



- (void)release{

     @try
        {
            [super release];
        }
     @catch(NSException* ex)
        {
            NSLog(@"Bug captured");
        }

    }
Run Code Online (Sandbox Code Playgroud)

额外的好处是,此代码对于应用程序中的每个对象都有效,因为它是 NSObject 上的一个类别。

不过,为了完整起见,如果您只是练习内存管理规则,那就没问题了。