Setting NSError within a block, using ARC

前端 未结 2 1660
无人共我
无人共我 2020-12-29 11:29

I wish to set an NSError pointer from within a block in a project using automatic reference counting. What follows is a simplified version of my code:

- (BOO         


        
相关标签:
2条回答
  • 2020-12-29 11:34

    Note: As of 2020, this workaround is no longer necessary.


    Try this:

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

    As for exactly why this is necessary, I'm still trying to get a grasp on that myself. I'll update this answer when I do. :)

    0 讨论(0)
  • 2020-12-29 11:55

    What is the correct way to set an NSError from within a block?

    As seen on "What's new in LLVM?" @ 14:55, there are two techniques to address the issue with the NSError which is implicitly autoreleasing.

    Easiest fix is to use __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:...];
            }
        }];
    }
    

    Second fix is to use __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;
        }
    
    0 讨论(0)
提交回复
热议问题