2

我正在创建一个可用于10.6及更高版本的可可应用程序的框架。Objective-C框架错误处理

该框架的目的是解析一个文本文件。

显然,有可能发生的错误,如找不到文件,权限问题等

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

我的想法是:

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

  2. 在主机应用程序注册它的第一个响应者与框架,捕获任何异常,将它们转换成NSError并传递给主机应用程序的响应链。

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

我已经阅读了错误和异常处理指南,但它们不包括这种情况,只描述应用程序本身的错误处理。

+1

我从来没有听说过任何传递响应链的NSErrors的代码。 (如果调用代码与任何NSResponders完全无关,如使用命令行工具那么该怎么办?)不管你做什么:不要这样做! –

+0

@KurtRevis,看看 - [NSResponder presentError:]和朋友,例如 –

+0

啊,这很有趣 - 我必须错过那些时,他们被添加到10.4。我期望一个较低级别的框架(就像在这种情况下,只是解析一个文本文件)将一个“NSError”交给它的调用者,并让UI代码处理演示文稿。 –

回答

1

我想说正确的做法是在可错误的所有方法直接使用自己NSError。我最近用我创建的一个实用程序类来完成这个任务,并且它工作得很好。然后,您可以让应用程序决定如何处理错误(崩溃,日志,其他),并且框架无需担心。

这里是私人类的方法我用来创建错误对象,以使得潜在的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; 
} 
+0

出于好奇,填充underlyingErrorDetail字典有什么意义?它没有被返回,所以我只能猜测它在代码中的其他地方使用。 – wadesworld

+0

@wadesworld是的,我还没有示例调用该方法的'posixError'版本,但也有其他的我忽略了。 undelyingError的要点是允许任意深度的信息,有点像Java异常的'根本原因'概念。我将编辑我的答案以添加示例调用。 – trojanfoe

1

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

报告错误给调用者正确的方法是通过一个NSError对象。您会注意到,许多Cocoa和Cocoa Touch方法完全包含一个NSError *参数。