是否会使用_block_copy()函数将捕获的__weak变量复制到堆中?

时间:2017-05-12 05:49:55

标签: objective-c memory-management objective-c-blocks

当捕获__strong变量的Block被复制到堆中时,该变量也会被复制到具有_block_copy()函数的堆中。

但是使用__weak变量会发生什么?

id __weak weakObj = someObj;
someBlock = [^() {
   //using __weak variable
} copy];

2 个答案:

答案 0 :(得分:0)

当一个块捕获任何非__block变量时,该变量总是被复制到一个独立的副本中,当创建块时保留,而不是复制块时。即使块移动到堆中也是如此。无论变量的类型是什么(无论是基本类型,还是ARC管理的强或弱指针类型),都是如此。

例如,如果在ARC关闭的情况下运行以下示例:

int foo = 5;
void (^someBlock)(void) = ^{
  NSLog(@"value in block: %d", foo);
};
foo = 6;
NSLog(@"value outside block: %d", foo); // logs "value outside block: 6"
someBlock();                            // logs "value in block: 5"
NSLog(@"block is: %@", someBlock);      // logs "block is: <__NSStackBlock__: 0x7fff523f0ba0>"

您会注意到该块从未移动到堆中,因为它最后是__NSStackBlock__(我在ARC关闭时控制了块的复制,因为ARC可能会隐式移动块在防守上堆。)您还会注意到,块创建后,块内变量的值不受块外部变量的赋值影响,证明变量是在赋值之前复制的(即块创建时)。这个演示是使用原始int完成的,以表明它适用于任何类型 - 它不仅适用于ARC管理的指针类型 - 但对于ARC管理的指针类型仍然如此无论是强者还是弱者。

答案 1 :(得分:-2)

我试过这个:

NSNumber *testNumber = [[NSNumber alloc] initWithInt:5];

NSNumber *__weak weakObj = testNumber;
NSLog(@"original weakObj address = %p",&weakObj);

id someBlock = [^() {
    NSLog(@"value in block:%ld",(long)weakObj.integerValue);
    NSLog(@"weakObj address inside block = %p",&weakObj);
} copy];

testNumber = [[NSNumber alloc] initWithInt:6];
NSLog(@"value outside:%ld",(long)testNumber.integerValue);

[someBlock invoke];

NSLog(@"weakObj address = %p",&weakObj);

结果是:

original weakObj address = 0x7fff5fbff750
value outside:6
value in block:5
weakObj address inside block = 0x1005023f0
weakObj address = 0x7fff5fbff750

<强>结论:

  1. 在块内,弱对象的内存地址被更改。因此,弱对象被复制到堆中。并且可以使用__block_copy()函数。

  2. 在块外,弱对象在复制后保留原始内存地址。