Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between a __weak and a __block reference?

I'm reading Xcode's documentation, and here is something that puzzles me:

__block typeof(self) tmpSelf = self; [self methodThatTakesABlock:^ {     [tmpSelf doSomething]; }]; 

The following is copied from the documentation:

A block forms a strong reference to variables it captures. If you use self within a block, the block forms a strong reference to self, so if self also has a strong reference to the block (which it typically does), a strong reference cycle results. To avoid the cycle, you need to create a weak (or __block) reference to self outside the block, as in the example above.

I don't understand what does 'a weak (or __block)' mean?

Is

__block typeof(self) tmpSelf = self; 

and

__weak typeof(self) tmpSelf = self; 

exactly the same here?

I found another piece in the document:

Note: In a garbage-collected environment, if you apply both __weak and __block modifiers to a variable, then the block will not ensure that it is kept alive.

So, I'm totally puzzled.

like image 754
HanXu Avatar asked Aug 02 '12 08:08

HanXu


People also ask

What does __ block do?

__block is a storage qualifier that can be used in two ways: Marks that a variable lives in a storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. And clang will generate a struct to represent this variable, and use this struct by reference(not by value).

What is strong reference and weak reference in Objective C?

A reference to an object is any object pointer or property that lets you reach the object. 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.

What is a weak reference Objective C?

Pointers that are not retained are often referred to as “weak” in Objective-C documentation that predates the garbage collector. These are references that are allowed to persist beyond the lifetime of the object. Unfortunately, there is no automatic way of telling whether they are still valid.


1 Answers

From the docs about __block

__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or created within the variable’s lexical scope. Thus, the storage will survive the destruction of the stack frame if any copies of the blocks declared within the frame survive beyond the end of the frame (for example, by being enqueued somewhere for later execution). Multiple blocks in a given lexical scope can simultaneously use a shared variable.

From the docs about __weak

__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.

So they are technically different things. __block is to stop your variable being copied from your external scope into your block scope. __weak is a self delimiting weak pointer.

Note I said technically, because for your case they will do (almost) the same thing. The only difference is if you are using ARC or not. If your project uses ARC and is only for iOS4.3 and above, use __weak. It ensures the reference is set to nil if the global scope reference is releases somehow. If your project doesn't use ARC or is for older OS versions, use __block.

There is a subtle difference here, make sure you understand it.

EDIT: Another piece to the puzzle is __unsafe_unretained. This modifier is almost the same as __weak but for pre 4.3 runtime environments. HOWEVER, it is not set to nil and can leave you with hanging pointers.

like image 72
Paul de Lange Avatar answered Oct 08 '22 19:10

Paul de Lange