阻止非平凡的循环

时间:2013-12-16 19:25:49

标签: ios objective-c memory-management automatic-ref-counting objective-c-blocks

我读了以下article,但我对以下段落感到困惑。

  

Apple文档说“然而,对于非平凡的周期,你应该使用”这种方法:

MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler =  ^(NSInteger result) {
    MyViewController *strongMyController = weakMyController;
    if (strongMyController) {
        // ...
        [strongMyController dismissViewControllerAnimated:YES completion:nil];
        // ...
    }
    else {
        // Probably nothing...
    }
};
  

首先,这个例子对我来说是错误的。自我怎么样?   如果块本身保留在块中,则取消分配并填空   completionHandler属性? completionHandler属性可以是   声明为assign或unsafe_unretained以允许该对象   在块被传递之后解除分配。我看不出原因   这样做。如果其他对象需要对象(self),则为块   传递的应该保留对象,因此保留块   不应该分配给一个属性。没有_ 弱/ _strong用法应该   参与此案。

  1. 他说“如果其他物品需要物体(自我):” 这里的需求是什么意思?它是这样的:他们需要自我,因为他们访问需要自我的块(传递给他们的块),所以他们需要自我。如果不是他的意思?

  2. 然后他说“因此不应该将区块分配给一个房产。” 但是,如果将来有多个对象需要块一些未定义的时间呢?所以,我们可以通过从这个属性获取块来传递它们。

  3. 我采取了错误的方式吗?

3 个答案:

答案 0 :(得分:3)

该文章的作者有点困惑,并且有些事情倒退了。

  

如果块本身是自我,那么如何自我解除分配并被填空   保留在completionHandler属性中?

如果该块保留在completionHandler中,则表示self具有对该块的强引用,这意味着只要self是块,该块就是活动的 - 不是其他方式。 self保留该块与self被解除分配无关。

  

completionHandler属性可以声明为assign或   unsafe_unretained允许对象在之后被释放   块被传递。

同样,completionHandler是强引用还是弱引用会影响块的生命周期。它与self生命周期所指向的对象无关。

  

如果其他对象需要对象(self),则传递的块   周围应该保留对象,因此块不应该   分配给一个财产。

没有。该对象保留该块。该块不保留该对象。

在大多数情况下是否需要代码示例中显示的模式是非常值得商榷的。但是,作者的推理是错误的。

答案 1 :(得分:0)

Blocks保留其中提到的变量,以便它们可以在它们首次出现的上下文中执行。当其中一个保留的块变量直接(平凡)或间接(非平凡)保留块时,您会得到一个循环。

例如,当objectA拥有一个提到objectA的块时,我们得到一个简单的循环:objectA - >块 - >对象A

// objectA owns a block property (declared as copy) called theBlock
objectA.theBlock = ^{
    // anything in the current scope can be mentioned safely in here, except:
    [objectA doSomething];
};

该文章的建议应该是通过在块中使用objectA指针的未保留副本来打破保留周期...

__unsafe_unretained ObjectAType *objectAUnretainedCopy = objectA;
// in an ARC project, @Rob points out that this is probably better qualified as __weak
objectA.theBlock = ^{
    // now we can mention anything in the current scope, including:
    [objectAUnretainedCopy doSomething];
};

现在objectA仍然保留了块,但是这个改进的块不会保留objectA。

一个非平凡的周期是相同的,只是拥有更长的所有权链,使得周期更难以识别。假设objectB保留一个保留(强)指向objectA ...

的指针
objectB.myObjectA = objectA;

现在在objectA的块中提到objectB是错误的,因为你最终得到了一个循环: objectB - > objectA - > theBlock - >对象B

objectA.theBlock = ^{
    // anything in the current scope can be mentioned safely in here, except:
    [objectB doSomething];
};

同样的解决方案适用。不要直接引用objectB,而是使用未保留的副本......

__unsafe_unretained ObjectBType *objectBUnretainedCopy = objectB;
// again, per @Rob, or __weak

答案 2 :(得分:0)

请参考以下博客,这是有道理的。它以更好的方式解释它。

https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/