【问题标题】:iPhone development: How to Catch Exception/NSError in Objective-C?iPhone 开发:如何在 Objective-C 中捕获异常/NSError?
【发布时间】:2010-11-15 22:58:02
【问题描述】:

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

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

我知道这个不起作用。因为release 从不引发异常。以下是我的问题:

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

这是我读到的

  • 一个。异常编程主题 Cocoa
  • 乙。错误处理编程
    可可指南

我来自经验丰富的 Microsoft 程序员背景,在这种情况下,捕获异常或意外异常总是可以防止我的程序在非常糟糕的环境中崩溃。

你们(Mac 天才程序员)是如何使无崩溃程序发生的?分享您的经验。

【问题讨论】:

    标签: iphone objective-c exception memory-management


    【解决方案1】:

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

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

    尝试这样做:

    NSString *str = [[NSString alloc] initWithString:@"a string"];
    [str release];
    [str release];
    

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

    [self dealloc];
    

    被自动调用。

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

    您可以做的是向 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");
            }
    
        }
    

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

    不过,如果您只是练习它们的内存管理规则,就可以了。

    【讨论】:

    • 感谢您的回答。您的回答帮助我更好地理解内存管理并扩展我对 Objective C 的了解。但是,我已经尝试过代码,它们从不崩溃(它们应该是,我发布了 4 次,如果可能的话,引用计数应该是 -3)。但根本没有发生崩溃,也没有抛出异常。我知道它有时会崩溃。但不知道什么时候。那么回到基础,有没有办法避免崩溃?
    • 不要关心保留计数。您永远不应该检查它,由于各种原因,它永远不是您认为应该的样子。您必须一次处理一种方法的内存管理。在 Stackoverflow 和 google 中搜索可可内存管理。有很多资源可以帮助您。一开始可能很难学习,但会变得更加自动化。
    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      测试测试测试测试测试测试

      您可以花一整天时间为可能的异常(实际上永远不会发生)编写异常处理代码,或者您可以创建完整的测试套件,只为实际发生的情况编写异常处理程序。

      这就是我几乎从不编写异常处理程序的原因。如果您修复了导致异常的潜在问题,那么您无需处理任何事情。

      当然,在某些情况下无法确保方法调用不会引发异常,你需要做好准备,但将所有内容都包装在 @try/@catch 块中绝对不是解决办法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-23
        • 2016-05-09
        • 2015-09-20
        • 2020-02-15
        • 1970-01-01
        • 2021-05-23
        • 2016-06-26
        • 1970-01-01
        相关资源
        最近更新 更多