Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strong reference to a weak references inside blocks

Why is it necessary to have a strong reference to a weak reference inside a block?

I understand that having a weak reference inside the block will avoid retain cycles. But why must there be a strong reference to the weak one again?

Background:
As described by Mason this is best practice.

I know the proper way to refer to self inside a block is to create a weak reference outside the block, and then a strong reference to that weak reference inside the block[...]

Example:

__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
    typeof(self) strongSelf = weakSelf;
    // code using strongSelf
});
like image 513
lukas_o Avatar asked May 22 '14 12:05

lukas_o


People also ask

What are strong and weak references?

A weak reference is just a pointer to an object that doesn't protect the object from being deallocated by ARC. While strong references increase the retain count of an object by 1, weak references do not. In addition, weak references zero out the pointer to your object when it successfully deallocates.

What are strong references and weak references in GC?

The garbage collector cannot collect an object in use by an application while the application's code can reach that object. The application is said to have a strong reference to the object. A weak reference permits the garbage collector to collect the object while still allowing the application to access the object.

Why do you generally create a weak reference when using self in a block?

For many of us, it's best practice to always use weak combined with self inside closures to avoid retain cycles. However, this is only needed if self also retains the closure. By adding weak by default you probably end up working with optionals in a lot of cases while it's actually not needed.

What is strong reference and weak reference in Objective C?

There are two types of object reference: Strong references, which keep an object “alive” in memory. Weak references, which have no effect on the lifetime of a referenced object.


1 Answers

Imagine that the last remaining strong reference to self is held on a different thread to the one that your block runs on.

Now this happens:

__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
    if (weakSelf != nil) {
       // last remaining strong reference released by another thread. 
       // weakSelf is now set to nil.
       [myArray addObject:weakSelf];
    }
});

This will crash with an NSInvalidArgument exception for adding nil to an array.

Making the reference strong before use removes the potential race condition and ensures that the pointer will always point to the same object.

If you are 100% certain that an object will only ever be referenced by one thread, it isn't strictly necessary to do this. But it's bad practice to make that assumption.

like image 91
Chris Devereux Avatar answered Oct 25 '22 23:10

Chris Devereux