【问题标题】:Obj-C Blocks as ParameterObj-C 块作为参数
【发布时间】:2013-01-24 10:41:34
【问题描述】:

我的代码中定义了一个可以多次调用的 ErrorBlock (errorBlock)。 虽然我只想被告知一次有关呼叫的信息,但我的想法是将我的 ErrorBlock (errorBlock) 包装在另一个 (pErrorBlock) 中并将其设置为 nil。

现在我想要一个清理方法,将 innerBlock 的引用设置为 nil。但是当我将内部块交给清理方法(测试 1)时,当我将内部 ErrorBlock 设置为 nil 自身(测试 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

【问题讨论】:

  • errorBlock = nil; 肯定没有任何效果,因为它是作为参数传递的......

标签: ios objective-c methods pass-by-reference block


【解决方案1】:

您正在按值传递块,像这样通过引用传递它。也让你在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);
}

【讨论】:

  • 好的.. 如果您给出ErrorBlock 的定义,那么我会提前 5 分钟回答您的问题。 :D 无论如何 +1 你的问题,因为它清楚了我制作块变量的概念:)
  • 调用 nil 应该是允许的。这就是为什么我宁愿把它放在外面。原因是我真正的清理方法需要多个块参数,我不想为所有这些测试 nil。
  • 是的,你可以在外面吃。但它没有用;)因为它会将一个 nil 分配给一个已经是 nil o_O 的指针
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 1970-01-01
  • 2019-09-06
  • 2019-03-19
  • 1970-01-01
相关资源
最近更新 更多