Is Block_copy recursive?

前端 未结 3 601
伪装坚强ぢ
伪装坚强ぢ 2020-12-30 07:32

I have some code that essentially boils down to this:

-(void)doSomethingWithBlock:(BlockTypedef)block
{
    [Foo doSomethingElseWithBlock:^() {
        block         


        
3条回答
  •  攒了一身酷
    2020-12-30 08:12

    The inner Block_copy() isn't really relevant here. What you want to keep track of is whether a given block lives on the stack or on the heap. Consider this code based on your example:

    @interface Foo : NSObject
    @end
    
    @implementation Foo
    
    typedef void(^BlockTypedef)(void);
    
    +(void)doSomethingElseWithBlock:(BlockTypedef)block
    {
      NSLog(@"block=%@", block);
      BlockTypedef myBlock = Block_copy(block);
      NSLog(@"myBlock=%@", myBlock);
      myBlock();
      Block_release(myBlock);
    }
    
    +(void)doSomethingWithBlock:(BlockTypedef)block
    {
      [Foo doSomethingElseWithBlock:^() {
        block();
      }];
    }
    @end
    
    int main (int argc, const char * argv[])
    {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
      int i = 3;
      BlockTypedef block = ^{ printf("i=%d\n", i); };
      NSLog(@"block=%@", block);
      [Foo doSomethingWithBlock:block];
      block();
      NSLog(@"block=%@", block);
      [pool drain];
      return 0;
    }
    

    This should be ok, but block and myblock are different kinds of blocks. block is a stack block and has the scope of the calling stack. It will exist until main() exits. myblock is a malloc (heap) block, and will exist until it is released. You need to make sure that you don't try to take a non-copied reference to block and use it after the stack is done. You can't stick block in an ivar without copying it.

    Joachim Bengtsson has the best write-up of this that I know of. @bbum has also written about it. (If bbum wanders in here and says I'm an idiot about this, then listen to him, but I think I'm right here.)

提交回复
热议问题