The problem is that your evaluteAndRecurse() block is capturing itself, which means if it will ever be copied (I don't believe it will be in your case, but in a few less trivial cases it may be), then it save himself and, therefore, will live forever, as there is nothing to break the cycle of retention.
Edit : Rami Al Zuhuri made a good point using __unsafe_unretained , the only link to the block is dangerous. As long as the block remains on the stack, this will work, but if the block needs to be copied (for example, it needs to go to the parent area), then __unsafe_unretained will free it. The following paragraph updates the recommended approach:
What you probably want to do here is use a separate variable, marked __unsafe_unretained , which also contains a block, and capture this separate variable. This will prevent its persistence. You can use __weak , but since you know that a block must be alive if called, there is no need to worry about (very minor) overhead of weak links. This will make your code look like
NSArray*(^__block __unsafe_unretained capturedEvaluteAndRecurse)(UIView*); NSArray*(^evaluateAndRecurse)(UIView*) = ^NSArray*(UIView *view) { ... [myPassedChildren addObjectsFromArray:capturedEvaluateAndRecurse(subview)]; }; capturedEvaluateAndRecurse = evaluteAndRecurse;
Alternatively, you can grab a pointer to a block that will have the same effect, but allow you to grab a pointer before creating the block, and not after it. This is a personal preference. It also allows you to omit __block :
NSArray*(^evaluateAndRecurse)(UIView*); NSArray*(^*evaluteAndRecursePtr)(UIView*) = &evaluateAndRecurse; evaluateAndRecurse = ^NSArray*(UIView*) { ... [myPassedChildren addObjectsFromArray:(*evaluateAndRecursePtr)(subview)]; };
Regarding the need for __block , this is a separate issue. If you don't have __block , then the block instance will actually capture the previous value of the variable. Remember that when a block is created, any captured variables that are not marked with __block are actually saved as a copy of their const state at the point where the block is instantiated. And since the block is created before it is assigned to a variable, this means that it captures the state of the variable capturedEvaluteAndRecurse until the destination, which will be nil (in ARC, otherwise it will be garbage memory).
In essence, you can imagine a specific instance of a block as being actually an instance of a hidden class that has ivar for each captured variable. Thus, with your code, the compiler will basically consider it something like:
Hope this makes it clear why it captures the previous value of evaluateAndRecurse instead of the current value.