iOS块。如何从块设置器中引用对象实例?

时间:2013-02-09 13:39:00

标签: ios objective-c-blocks retain-cycle

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

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

我用块初始化属性。在block中,我引用了对象实例:

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

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

谢谢, 道格

2 个答案:

答案 0 :(得分: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);

答案 1 :(得分:1)

因为你在块中使用“thing”,所以block将保持一个强大的指向“thing”的指针,直到块超出范围或块本身离开堆(即没有人强烈地指向块) - 这是你想要的,因为块首先被移动然后代码在稍后的某个点执行,所以你显然不希望块在第一次移动块而不执行之后松开指向“thing”的指针。

现在,你有一个块保持一个强大的指向“thing”的指针,你有“东西”通过它的属性“setup”维护一个强大的指向块的指针。现在,“东西”和块都不能逃脱堆。那是因为总会有一个强大的指针指向它们(彼此的指针)。这称为记忆“循环”。

答案是宣称“事物”是弱者:

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

在块中使用“weakThing”。这解决了这个问题,因为现在块只有一个指向“weakThing”的弱指针。

希望这是有帮助的