0

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

例如,当我调用 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;
}
4

3 回答 3

4

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

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

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

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

为什么 `&`(和号)放在一些方法参数的前面?

示例实现:

    - (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;
    }
于 2013-10-06T21:47:41.467 回答
3

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

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

现在,当使用双指针时,您需要在编程中采取防御措施。首先,您必须确保erroris not的值nil,然后*error是 is nil。您必须这样做,因为您不知道如何对现有对象进行明智的内存管理。例如:

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

会是正确的。但

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

是一个问题,因为您的save:方法不会 if erroris retainedor 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读作“错误地址”。

于 2013-10-06T22:13:03.950 回答
2

我们需要注意这里的语法。当我们将 NSError 传递给方法时: + (instancetype)stringWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError * *)error

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

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

于 2013-10-06T21:48:30.857 回答