Objective c 块拷贝是递归的吗?

Objective c 块拷贝是递归的吗?,objective-c,cocoa,objective-c-blocks,Objective C,Cocoa,Objective C Blocks,我有一些代码基本上可以归结为: -(void)doSomethingWithBlock:(BlockTypedef)block { [Foo doSomethingElseWithBlock:^() { block(); }]; } Foo doSomethingElseWithBlock:对接收到的块调用Block\u copy和Block\u release。这在外部范围内也是必要的,还是内部的块拷贝将处理这个问题?我引用苹果开发者文档网站上的指南: 复制块

我有一些代码基本上可以归结为:

-(void)doSomethingWithBlock:(BlockTypedef)block
{
    [Foo doSomethingElseWithBlock:^() {
        block();
    }];
}
Foo doSomethingElseWithBlock:
对接收到的块调用
Block\u copy
Block\u release
。这在外部范围内也是必要的,还是内部的
块拷贝将处理这个问题?

我引用苹果开发者文档网站上的指南:

复制块时,将复制该块内对其他块的任何引用(如有必要),并可以复制整个树(从顶部)。如果有块变量,并且从块内参照块,则将复制该块

复制基于堆栈的块时,会得到一个新块。但是,如果复制基于堆的块,只需增加该块的retain计数,并将其作为copy函数或方法的返回值返回

内部
Block\u copy()
在这里实际上并不相关。您要跟踪的是给定块是位于堆栈上还是位于堆上。根据你的例子考虑这个代码:

@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;
}
这应该可以,但是
block
myblock
是不同类型的块<代码>块
是堆栈块,具有调用堆栈的范围。它将一直存在,直到退出
main()
myblock
是一个malloc(heap)块,它将一直存在,直到被释放。您需要确保不要尝试获取对
块的未复制引用,并在堆栈完成后使用它。如果不复制ivar,则无法在ivar中粘贴
block


这是我所知道的最好的一篇文章。我也写过。(如果bbum在这里闲逛,说我是个白痴,那就听他的,但我想我就在这里。)

是的,这是安全的。你不需要复印。当
-[Foo doSomethingElseWithBlock:
复制文本块时,它会将内部块复制到堆中

我写了一些测试代码来向自己证明这是真的;查看调用
Block\u copy(block2)
时如何将
printer
(仅在
block1
中使用)从堆栈复制到堆

#include <Block.h>
#include <dispatch/dispatch.h>
#include <stdio.h>

typedef void (^void_block)();

class ScopedPrinter {
  public:
    ScopedPrinter() {
        printf("construct %p\n", this);
    }
    ScopedPrinter(const ScopedPrinter& other) {
        printf("copy %p <- %p\n", this, &other);
    }
    ~ScopedPrinter() {
        printf("destroy %p\n", this);
    }
};

void_block invoke(void_block other) {
    printf("other %p\n", (void*)other);
    void_block block2 = ^{
        printf("other %p\n", (void*)other);
        other();
    };
    printf("block2 created\n");
    block2 = Block_copy(block2);
    printf("block2 copied\n");
    return block2;
}

void_block make_block() {
    ScopedPrinter printer;
    printf("printer created\n");
    void_block block1 = ^{
        printf("block1 %p\n", &printer);
    };
    printf("block1 created\n");
    return invoke(block1);
}

int main() {
    void_block block = make_block();
    block();
    Block_release(block);
    return 0;
}
#包括
#包括
#包括
typedef void(^void_block)();
类作用域{
公众:
ScopedInter(){
printf(“构造%p\n”,this);
}
ScopedInter(const ScopedInter和其他){

printf(“复制%p此时我的应用程序不是特别可运行的,所以不是。我确实发现了这样一个问题:块可能包含块文字表达式。内部块中使用的任何变量都会导入到所有封闭块范围中,即使不使用这些变量。这包括常量导入和_块变量。“然而,在这种情况下,它是一个包含块的块文字,而不是其中给出的顺序。即使
make_block()
声明
block1
\u block void_block block1
(例如,它可以是递归的),您仍然是安全的。
invoke()
不必担心被调用方的存储说明符。
construct 0x7fff6a23fa70
printer created
copy 0x7fff6a23fa50 <- 0x7fff6a23fa70
block1 created
other 0x7fff6a23fa30
block2 created
copy 0x10a700970 <- 0x7fff6a23fa50
block2 copied
destroy 0x7fff6a23fa50
destroy 0x7fff6a23fa70
other 0x10a700950
block1 0x10a700970
destroy 0x10a700970