定义返回错误的方法

时间:2013-10-06 21:38:25

标签: objective-c out-parameters

如何定义返回错误和值的方法?

例如,当我调用managedObjectContext保存方法时,该方法返回一个布尔值以及一个错误:

if(![context save:&error]) {
    NSLog(@"%@", error);
}

您能否给我一个直截了当的方法定义示例?

编辑/更新:同样,如何传回多个错误。我在下面做错了(我可能还不明白这个概念),这不起作用:

NSArray *errors = nil;
[self throwMultipleErrors:&errors];
for(id error in errors) {
    NSLog(@"Muliple error: %@", error);
}...

-(BOOL)throwMultipleErrors:(NSMutableArray **) errors {
    [*errors addObject:@"First Error"];
    [*errors addObject:@"Second Error"];
    [*errors addObject:@"Third Error"];

    return YES;
}

3 个答案:

答案 0 :(得分:3)

在您的示例中,方法签名为:

- (BOOL)save:(NSError **)error;

这允许调用者传入NSError作为地址而不是指针(指向指针**&的指针),然后该方法可以从另一个指定范围。如果方法返回false,则调用者可以检查错误变量的内容,如示例所示。

有关在变量和&签名前使用(NSError **)的详细信息,请参阅此问题。

Why is `&` (ampersand) put in front of some method parameters?

示例实施:

    - (BOOL)save:(NSError **)error
    {
       NSAssert(error != nil, @"Passed NSError must be nil!");
       // Attempt to do a save
       if (saveDidFail) {
             NSDictionary *userInfo = [NSDictionary dictionaryWithObjectAndKeys:@"Save Failed", kCustomErrorKey, nil];
             *error = [NSError errorWithDomain:@"domain" code:999 userInfo:userInfo];
             return NO;
       } 
       return YES;
    }

答案 1 :(得分:3)

使用您的示例,方法签名将是:

-(BOOL)save:(NSError**)error;

现在,当使用双指针时,你需要在编程中保持防守。首先,您必须确保error的值不是nil,然后*errornil。您必须执行此操作,因为您不知道如何使用现有对象进行内存管理。例如:

NSError *error = nil;
[self save:&error];

是正确的。但

NSError *error = [[NSError alloc] init];
[self save:&error];

是一个问题,因为如果save:errorretained,则autoreleased方法不会出现。如果您release它是autoreleased,那么您的应用最终会崩溃。相反,如果你没有release而它是retained你就会泄漏内存。我建议使用断言检查这一点,以便在签入代码之前快速解决问题。

NSAssert(!error || !*error, @"*error must be nil!");

最后,在设置*error时,您必须确保error不是nil。永远不允许您设置内存地址0x0的值。如果您没有检查并且是否将nil传递给方法,那么如果您尝试设置它,崩溃。

if (error)
{
    *error = [NSError ...];
    return NO;
}

要返回一个数组,我会做这样的事情:

-(BOOL)throwMultipleErrors:(NSError **) error {

    NSAssert(!error | !*error, @"*error must be nil");

    NSMutableArray *errorList = nil;

    if (error)
        errorList = [NSMutableArray array];


    [errorList addObject:@"First Error"];
    [errorList addObject:@"Second Error"];
    [errorList addObject:@"Third Error"];

    if (error && [errorList count] > 0)
    {
        *error = [NSError errorWithDomain:@"Some error"
                                     code:0
                                 userInfo:@{@"suberrors" : [NSArray arrayWithArray:errorList]}];
        return NO;
    }

    return YES;
}

请注意,返回数组是不可变的,并在方法内实例化。这个数组之外没有理由在这个方法之外是可变的,并且数组在它之外被实例化。将数组封装在NSError中允许它轻松地适应现有的NSError方法链。

注释

当然,您实际上会将[self save:&error];调用放入if()语句中以检查返回值。但请注意,我们传递的是&error,而不仅仅是error。这是因为我们需要将指针传递给error,而不是error&error读作“错误的地址。”

答案 2 :(得分:2)

我们需要在这里注意语法。 当我们将NSError传递给方法时:     +(instancetype)stringWithContentsOfFile:(NSString *)路径编码:(NSStringEncoding)enc错误:(NSError * *)错误

我们将句柄(指针指针)交给尚未初始化的错误对象。如果被叫消息遇到麻烦,它将初始化并填充错误对象。它不会“返回”错误,只需将值填入传递的参数。

因此,如果我想定义一条返回值的消息,并且还需要一个错误参数,请按照以下教程操作: http://www.cimgf.com/2008/04/04/cocoa-tutorial-using-nserror-to-great-effect/