复制与Block_copy()相同吗?

时间:2014-06-20 04:38:52

标签: objective-c objective-c-blocks

它们是否相同,copyBlock_copy()?怎么样?或者,如果没有,有什么区别?

我对此感到好奇,所以我决定做一些研究。

看看我的答案是什么。

2 个答案:

答案 0 :(得分:5)

最后,我找到了答案。 copyBlock_copy()相同,但不完全相同。

这是我发现的:


让我们来看看块的类别,其中有3个:

  1. __NSGlobalBlock__ - 如果您实现了一个没有任何对块外部的引用的块,您将获得此类的块。

    void(^block)() = ^{ NSLog(@"GRAZZZZ"); };
    
  2. __NSStackBlock__ - 如果你实现了一个带有一个或多个对块外部的引用的块,你将获得这个类的一个块(当你运行时,你会得到这个块)仅限非ARC 环境。在ARC env中,ARC会自动为您复制)。

    // NON-ARC CODE
    int theOutsider = 1234;
    void(^block)() = ^{ NSLog(@"%d", theOutsider); };
    
  3. __NSMallocBlock__ - 如果您复制__NSStackBlock__块,您将获得此类的块。

    int theOutsider = 1234;
    void(^block1)() = [^{ NSLog(@"%d", theOutsider); } copy]; // NON-ARC VERSION
    void(^block2)() = ^{ NSLog(@"%d", theOutsider); }; // ARC VERSION
    
  4. 对于__NSGlobalBlock__,当您致电copy时,它什么都不做,只需返回。所以,请忽略它。没有必要移动任何东西堆。下面是-[__NSGlobalBlock copy](超级类)的集合:

    CoreFoundation`-[__NSGlobalBlock copy]:
       0x7fff8bd016f0:  pushq  %rbp
       0x7fff8bd016f1:  movq   %rsp, %rbp
       0x7fff8bd016f4:  movq   %rdi, %rax
       0x7fff8bd016f7:  popq   %rbp
       0x7fff8bd016f8:  ret    
       0x7fff8bd016f9:  nopl   (%rax)
    

    对于__NSStackBlock____NSMallocBlock__,当您向他们致电copy时,他们会转发至其超级copy的{​​{1}}方法。这是OS X 10.9 SDK上的汇编代码:

    -[NSBlock copy]

    iOS 7.1 SDK上的汇编代码:

    CoreFoundation`-[NSBlock copy]:
       0x7fff8bcc86a0:  pushq  %rbp
       0x7fff8bcc86a1:  movq   %rsp, %rbp
       0x7fff8bcc86a4:  pushq  %rbx
       0x7fff8bcc86a5:  pushq  %rax
       0x7fff8bcc86a6:  movq   %rdi, %rbx
       0x7fff8bcc86a9:  callq  0x7fff8be360ac            ; symbol stub for: objc_collectingEnabled
       0x7fff8bcc86ae:  movq   %rbx, %rdi
       0x7fff8bcc86b1:  addq   $0x8, %rsp
       0x7fff8bcc86b5:  testb  %al, %al
       0x7fff8bcc86b7:  je     0x7fff8bcc86c0            ; -[NSBlock copy] + 32
       0x7fff8bcc86b9:  popq   %rbx
       0x7fff8bcc86ba:  popq   %rbp
       0x7fff8bcc86bb:  jmpq   0x7fff8be361f6            ; symbol stub for: _Block_copy_collectable
       0x7fff8bcc86c0:  popq   %rbx
       0x7fff8bcc86c1:  popq   %rbp
       0x7fff8bcc86c2:  jmpq   0x7fff8be361f0            ; symbol stub for: _Block_copy
       0x7fff8bcc86c7:  nopw   (%rax,%rax)
    

    正如您在代码中看到的那样,CoreFoundation`-[NSBlock copy]: 0x17949d0: pushl %ebp 0x17949d1: movl %esp, %ebp 0x17949d3: popl %ebp 0x17949d4: jmp 0x18d3d8a ; symbol stub for: _Block_copy 0x17949d9: nopl (%eax) 会调用-[NSBlock copy]

    _Block_copy足够了,让我们来看看copy。它在Block_copy()中定义为:

    Block.h

    #define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__))) 也会调用Block_copy() !!


    到目前为止,我可以总结一下 _Block_copycopy是一样的!

    希望这可以帮助有同样好奇心的人:D。

答案 1 :(得分:0)

当用于块指针类型的表达式时,方法copy和函数Block_copy()是相同的。同样,方法release和函数Block_release()是相同的。方法copyrelease只是更多的Objective-C消息传递方式,因为块是Objective-C中的对象,并且使用retainrelease进行内存管理,就像其他Cocoa一样对象。另一方面,在C / C ++中使用时,只能使用Block_copy()Block_release()来管理块。