سؤال

I have an object with a property that points to a block:

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

I initialize the property with a block. Within the block I refer to the object instance:

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

thing.setup = ^() {

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

However I get compile warnings about a retain loop:

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

What is the correct way to do this?

Thanks, Doug

هل كانت مفيدة؟

المحلول

you have to assign thing as weak ref:

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

thing.setup = ^() {

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

or you could provide thing as Parameter to the block:

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

thing.setup = ^(Thing *localThing) {

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

نصائح أخرى

Because you are using "thing" inside the block, block will maintain a strong pointer to "thing" until the block goes out of scope or the block itself leaves the heap (i.e. no one points strongly to the block anymore) - which is what you want because blocks are first traveled and then the code is executed at some later point so you obviously do not want the block to loose the pointer to "thing" after the block is first traveled without execution.

Now, you have the block maintaining a strong pointer to "thing" and you have "thing" maintaining a strong pointer to the block through its property "setup". Neither "thing" nor the block can ever escape the heap now. That’s because there will always be a strong pointer to both of them (each other’s pointer). This is called a memory “cycle.”

The answer is to declare "thing" as weak:

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

And use "weakThing" in the block. This solves the problem because now the block only has a weak pointer to "weakThing" . "thing" still has a strong pointer to the block through its property setup, but that’s okay.

Hope this was helpful

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top