Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

blocks, self, retain cycles

I'm having a bit of trouble getting my head around referencing self within a block, and not creating a retain cycle.

Can you let me know if my understanding is correct:

If I ever reference self within a block, it will create a retain cycle, and instead I should be creating a weak reference to self outside of the block and then using that weak reference inside the block?

Thanks!

like image 924
Wise Shepherd Avatar asked Sep 11 '12 01:09

Wise Shepherd


People also ask

Which of the following can cause a retain cycle?

Structs and Classes A choice between a struct and a class can cause a retain cycle. Both structs and classes can have constants, variables, functions and protocols.

What is retaining cycle?

Retain Cycle is the condition When 2 objects keep a reference to each other and are retained, it creates a retain cycle since both objects try to retain each other, making it impossible to release. Here The "Grandparent" retains the "parent" and "parent" retains the "child" where as "child" retains the "parent"..

What's retain cycle how you can avoid in Swift?

In order to prevent this retain cycle, we need to declare at least one of the variable as weak or unowned. We can break the retain cycle with adding a weak keyword before either the driver property of the Car class or the car property of the Person class.

What is strong and weak in Objective C?

strong is the default. An object remains “alive” as long as there is a strong pointer to it. weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.


1 Answers

Yes, that is correct, with a few exceptions:

A retain cycle only happens if self ends up retaining the block indirectly, e.g. setting property myblock on property of self myproperty:

self.myproperty.myblock = ^{ [self dosomething]; }; // ERROR: Retain Cycle

However, a retain cycle doesn't (usually) happen when using blocks for something like dispatch code, like this:

dispatch_async(dispatch_get_main_queue(), ^{ [self dosomething]; }); // Safe, dispatch_async will not be retained by you

Unless of course you call that dispatch_async function inside a block that has the criteria for being a retain cycle.

It is really confusing, and it's something I hope gets fixed. Now, for my own opinion:


It wasn't always the case, in pre-ARC code this wasn't an issue, but since blocks now automatically retain any objects they capture, it's an issue.

I wish this would get fixed, as it'd be a quite easy fix, by having self's type be a __weak instancetype const instead of a instancetype const. It would also solve some issues with creating class clusters in ARC, which admittedly isn't the largest of issues, but it still exists.

As far as advantages to retain cycles, there are not many.

like image 175
Richard J. Ross III Avatar answered Oct 01 '22 03:10

Richard J. Ross III