使用ARC在块中设置NSError

时间:2011-08-02 05:41:19

标签: objective-c objective-c-blocks automatic-ref-counting nserror

我希望在项目的块中使用设置NSError指针 自动参考计数。以下是我的代码的简化版本:

- (BOOL)frobnicateReturningError:(NSError **)error
{
    NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];

    __block Frobnicator *blockSelf = self;
    [items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
        [blockSelf doSomethingWithItem:item error:error];
    }];
}

这个编译,但给定error可能会被修改 doSomethingWithItem我尝试为块创建一个本地NSError 修改,然后用于设置原始error之后 枚举(我没有显示):

- (BOOL)frobnicateReturningError:(NSError **)error
{
    NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];

    __block Frobnicator *blockSelf = self;
    __block NSError *blockError = nil;
    [items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
        [blockSelf doSomethingWithItem:item error:&blockError];
    }];
}

无法使用以下错误进行编译:

  

将非本地对象的地址传递给__autoreleasing参数以进行回写

Google搜索此错误只会返回Clang源代码本身的结果。

一个似乎有用但有点难看的解决方案是有一个内部和外部错误指针:

- (BOOL)frobnicateReturningError:(NSError **)error
{
    NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];

    __block Frobnicator *blockSelf = self;
    __block NSError *outerError = nil;
    [items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
        NSError *innerError = nil;
        [blockSelf doSomethingWithItem:item error:&innerError];
        outerError = innerError;
    }];
}

在块中设置NSError的正确方法是什么?

2 个答案:

答案 0 :(得分:8)

试试这个:

// ...
__block NSError *blockError = nil;
[items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
    NSError *localError = nil;
    if (![blockSelf doSomethingWithItem:item error:&localError]) {
        blockError = localError;
    }
}];
// ...

至于为什么这是必要的,我仍然试图掌握这一点。当我这样做时,我会更新这个答案。 :)

答案 1 :(得分:1)

  

在块中设置NSError的正确方法是什么?

如" What's new in LLVM?" @ 14:55,有两种技术可以解决NSError的问题,它隐式自动释放。

最简单的解决方法是使用__strong

- (BOOL)frobnicateReturningError:(NSError *__strong *)error
{
    NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];

    __block Frobnicator *blockSelf = self;

    [items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
        NSError *innerError = nil;
        [blockSelf doSomethingWithItem:item error:&innerError];
        if(innerError && error) {
          *error = [NSError errorWithDomain:...];
        }
    }];
}

第二个修复是使用__block

- (BOOL)frobnicateReturningError:(NSError **)error
{
        NSArray *items = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];

        __block Frobnicator *blockSelf = self;
        __block NSError *strongError = nil;

        [items enumerateObjectsUsingBlock:^(id item, NSUInteger idx, BOOL *stop) {
            NSError *innerError = nil;
            [blockSelf doSomethingWithItem:item error:&innerError];
            if(innerError) {
              strongError = [NSError errorWithDomain:...];
            }
        }];
        if (error) *error = strongError;
    }