0

我有一个具有指向块的属性的对象:

typedef void (^ThingSetter)();
@property(nonatomic, strong) ThingSetter setup;

我用一个块初始化属性。在blockI 中指的是对象实例:

Thing *thing = [[Thing alloc] init];

thing.setup = ^() {

    plainOleCFunction(thing.number);
    [thing doSomethingWithString:@"foobar"];
};

但是,我收到有关保留循环的编译警告:

capturing 'thing' strongly in this block is likely to lead to a retain cycle
block will be retained by the captured object

这样做的正确方法是什么?

谢谢,道格

4

2 回答 2

4

你必须指定thing为弱参考:

Thing *thing = [[Thing alloc] init];
__weak Thing *weakThing = thing;

thing.setup = ^() {

    plainOleCFunction(weakThing.number);
    [weakThing doSomethingWithString:@"foobar"];
};

或者您可以thing作为参数提供给块:

Thing *thing = [[Thing alloc] init];

thing.setup = ^(Thing *localThing) {

    plainOleCFunction(localThing.number);
    [localThing doSomethingWithString:@"foobar"];
};
thing.setup(thing);
于 2013-02-09T13:53:05.263 回答
1

因为您在块内使用“事物”,所以块将保持指向“事物”的强指针,直到块超出范围或块本身离开堆(即不再有人强烈指向块) - 这就是你想要,因为块首先被移动,然后代码在稍后的某个时间点执行,所以你显然不希望块在没有执行的情况下首次移动块后释放指向“事物”的指针。

现在,您让块维护指向“事物”的强指针,并且您让“事物”通过其属性“设置”维护指向块的强指针。“东西”和块现在都无法逃脱堆。那是因为总会有一个指向它们的强指针(彼此的指针)。这称为记忆“循环”。</p>

答案是将“事物”声明为弱:

事物 *thing = [[事物分配] init];
__weak 事物 *weakThing = 事物;

并在块中使用“weakThing”。这解决了问题,因为现在该块只有一个指向 "weakThing" 的弱指针。"thing" 通过其属性设置仍然有一个指向块的强指针,但这没关系。

希望这有帮助

于 2013-02-09T14:16:35.450 回答