【问题标题】:Objective-C Framework Error HandlingObjective-C 框架错误处理
【发布时间】:2012-05-27 02:41:43
【问题描述】:

我正在创建一个框架供 10.6 及更高版本的 Cocoa 应用程序使用。

框架的目的是解析文本文件。

显然,可能会出现错误,例如找不到文件,权限问题等。

在框架内处理错误并通知宿主应用程序的正确方法是什么?

我的想法是:

  1. 什么都不做,让宿主应用程序捕获任何异常。

  2. 让宿主应用程序向框架注册它的第一响应者,捕获任何异常,将它们转换为 NSError 并将它们传递给宿主应用程序的响应者链。

这些选项中的任何一个都有意义吗?还有其他选择吗?处理这个问题的正确方法是什么?

我已阅读错误和异常处理指南,但它们并未涵盖这种情况,仅描述了应用程序本身的错误处理。

【问题讨论】:

  • 我从未听说过任何代码将 NSErrors 传递到响应者链上。 (如果调用代码与任何 NSResponder 完全无关怎么办,比如在命令行工具中?)无论你做什么:不要那样做!
  • @KurtRevis,然后查看 -[NSResponder presentError:] 和朋友
  • 啊,这很有趣——当它们被添加到 10.4 时,我一定错过了。我希望一个较低级别的框架(在这种情况下,只是解析一个文本文件)会将NSError 交给它的调用者,并让 UI 代码处理演示文稿。

标签: objective-c cocoa frameworks exception-handling error-handling


【解决方案1】:

我想说正确的方法是在所有可能出错的方法中直接使用NSError。我最近使用我创建的实用程序类完成了此操作,并且效果很好。然后,您允许应用程序决定如何处理错误(崩溃、日志、其他内容),框架无需担心。

这是我用来创建错误对象的 private 类方法,允许潜在的 POSIX 错误(errno 等):

#pragma mark - Private Methods

- (NSError *)error:(NSString *)localizedDescription
              code:(EZipFileError)code
   underlyingError:(NSError *)underlyingError
{
    NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
    [errorDetail setValue:localizedDescription forKey:NSLocalizedDescriptionKey];
    if (underlyingError != nil)
    {
        [errorDetail setValue:underlyingError forKey:NSUnderlyingErrorKey];
    }
    return [NSError errorWithDomain:@"MyErrorDomain"
                               code:(NSInteger)code
                           userInfo:errorDetail];
}

- (NSError *)error:(NSString *)localizedDescription
              code:(EZipFileError)code
{
    return [self error:localizedDescription
                  code:code
       underlyingError:nil];
}

- (NSError *)error:(NSString *)localizedDescription
              code:(EZipFileError)code
        posixError:(int)posixError
{
    NSMutableDictionary *underlyingErrorDetail = [NSMutableDictionary dictionary];
    [underlyingErrorDetail setValue:[NSString stringWithUTF8String:strerror(posixError)]
                             forKey:NSLocalizedDescriptionKey];
    NSError *underlyingError = [NSError errorWithDomain:NSPOSIXErrorDomain
                                                    code:posixError
                                                userInfo:underlyingErrorDetail];
    return [self error:localizedDescription
                  code:code
       underlyingError:underlyingError];
}

具体用法如下:

if (![self isOpen])
{
    if (error != NULL)
    {
        *error = [self error:@"File is not open"
                        code:ErrorNotOpen];
    }
    return nil;
}

这是一个使用该方法的底层 POSIX 错误版本的示例:

filefp = fopen([filename UTF8String], "rb");
if (filefp == NULL)
{
    if (error != NULL)
    {
        *error = [self error:@"Failed to open file"
                        code:ErrorOpenFileFailed
                  posixError:errno];
    }
    return NO;
}

【讨论】:

  • 出于好奇,填写underlyingErrorDetail字典有什么意义?它没有返回,所以我只能猜测它在您的代码中的其他地方使用过。
  • @wadesworld 是的,我没有展示对该方法的posixError 版本的示例调用,但还有其他一些我遗漏了。 undelyingError 的重点是允许任意深度的信息,有点像 Java Exception 'root cause' 的概念。我将编辑我的答案以添加示例调用。
【解决方案2】:

异常应该只用于 Objective-C 中的终端错误。更具体地说,Cocoa 和 Cocoa Touch 不保证跨边界抛出的异常会从另一端出来,因此您不应该使用异常来处理错误。

向调用者报告错误的正确方法是通过 NSError 对象。您会注意到许多 Cocoa 和 Cocoa Touch 方法都包含一个 NSError* 参数来实现该目的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 2011-09-07
    相关资源
    最近更新 更多