使用您的示例,方法签名将是:
-(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读作“错误地址”。