我的代码中定义了一个ErrorBlock(errorBlock),可以多次调用。
尽管我只想知道一次有关该调用的信息,所以我的想法是将我的ErrorBlock(errorBlock)包装在另一个(pErrorBlock)中,并将该值设置为nil。

现在,我想要一个清理方法,将innerBlock的引用设置为nil。但是,当我将内部块交给清除方法(测试1)时,与设置内部ErrorBlock nil self(测试2)时,我得到的结果不同。

如何通过测试1的代码(稍作修改)获得测试2的结果?

我的首次测试,结果是我不了解:

-(void)testBlocks{
    __block ErrorBlock pErrorBlock= ^(void){
        NSLog(@"Foo");
    };
    NSLog(@"test: %p",pErrorBlock);

    ErrorBlock errorBlock = ^(void){
        dispatch_async(dispatch_get_main_queue(), ^{
            if(pErrorBlock){
                NSLog(@"call: %p",pErrorBlock);
                pErrorBlock();
            }

            [self cleanupErrorBlockWith:pErrorBlock];
        });
    };

    errorBlock();
    errorBlock();
}

- (void) cleanupErrorBlockWith:(ErrorBlock)errorBlock{

    NSLog(@"cleanup: %p",errorBlock);
    errorBlock = nil;
    NSLog(@"after cleanup: %p",errorBlock);
}

结果:
2013-02-08 16:39:04.484 Tests[9501:907] test: 0x3a6ba8
2013-02-08 16:39:04.496 Tests[9501:907] call: 0x3a6ba8
2013-02-08 16:39:04.497 Tests[9501:907] Foo
2013-02-08 16:39:04.498 Tests[9501:907] cleanup: 0x3a6ba8
2013-02-08 16:39:04.499 Tests[9501:907] after cleanup: 0x0
2013-02-08 16:39:04.500 Tests[9501:907] call: 0x3a6ba8
2013-02-08 16:39:04.501 Tests[9501:907] Foo
2013-02-08 16:39:04.502 Tests[9501:907] cleanup: 0x3a6ba8
2013-02-08 16:39:04.503 Tests[9501:907] after cleanup: 0x0

我的第二项测试是预期结果:
-(void)testBlocks{
    __block ErrorBlock pErrorBlock= ^(void){
        NSLog(@"Foo");
    };
    NSLog(@"test: %p",pErrorBlock);

    ErrorBlock errorBlock = ^(void){
        dispatch_async(dispatch_get_main_queue(), ^{
            if(pErrorBlock){
                NSLog(@"call: %p",pErrorBlock);
                pErrorBlock();
                NSLog(@"cleanup: %p",pErrorBlock);
                pErrorBlock = nil;
                NSLog(@"after cleanup: %p",pErrorBlock);
            }
        });
    };

    errorBlock();
    errorBlock();
}

结果:
2013-02-08 16:42:18.485 Tests[9540:907] test: 0x3a6ba8
2013-02-08 16:42:18.496 Tests[9540:907] call: 0x3a6ba8
2013-02-08 16:42:18.498 Tests[9540:907] Foo
2013-02-08 16:42:18.499 Tests[9540:907] cleanup: 0x3a6ba8
2013-02-08 16:42:18.500 Tests[9540:907] after cleanup: 0x0

最佳答案

您正在按值传递块,像这样通过引用传递。同时也将cleanupErrorBlockWith:调用移到if语句中。

-(void)testBlocks{
    __block ErrorBlock pErrorBlock= ^(void){
        NSLog(@"Foo");
    };
    NSLog(@"test: %p",pErrorBlock);

    ErrorBlock errorBlock = ^(void){
        dispatch_async(dispatch_get_main_queue(), ^{
            if(pErrorBlock){
                NSLog(@"call: %p",pErrorBlock);
                pErrorBlock();
                [self cleanupErrorBlockWith:&pErrorBlock];
            }
        });
    };

    errorBlock();
    errorBlock();
}


- (void) cleanupErrorBlockWith:(ErrorBlock*)errorBlock{
    NSLog(@"cleanup: %p",*errorBlock);
    *errorBlock = nil;
    NSLog(@"after cleanup: %p",*errorBlock);
}

08-27 14:40