For instance:
[self.contentWrapperView addGestureRecognizer:
[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender,
UIGestureRecognizerState state,
CGPoint location) {
if (self.customEditing) {
[self setEditingMode:NO Animated:YES];
}
}]];
Where contentWrapperView
is a strong property on self
, and presuming contentWrapperView
has a strong reference to the recognizer block. Is using self
in the block going to lead to a retain cycle? This is the only part I don't quite understand.
Think about a retain cycle in terms of what it actually is: a retention of yourself by an object that you own.
In Cocoa and Cocoa-Touch's terms, that means that any variable that you own strongly cannot, in turn, own you strongly. This is often gotten around by declaring a property that needs to own its parent
weak
,unsafe_unretained
orassign
. This gets complicated by blocks, which, acting as closures typically do, capture const or retained references to every variable within them (obviously, complicated even further by the__block
qualifier).Instead of looking at this from the standpoint of the block, I'll try to abstract it into an example with two classes, which is often more approachable for those in an OO lang:
Let's say I have class
MyImportantObject
, which needs to do some work with another classMyWorkerClass
. We'd usually want a strong references toMyWorkerClass
, because maybe we want it to stick around so we can do a little more work later on, or continue to call the same worker method over and over:In turn, our worker needs a stable reference to all of
MyImportantObject
's properties it needs to work (else it can't work!). So what blocks that referenceself
do, instead of taking a const or retained references to every variable, they take a retained reference to their parent!What this means is that if you attempted to use
MyImportantObject
's worker object, they'd retain each other, and neither would be deallocated properly! Huge no-no.By shunting
self
into a__weak
(or__block
under MRC) pointer, we instead get a reference that looks like this:No more retain cycles, everybody's happy, everybody gets deallocated properly when the parent goes the way of the dinosaur.
But there is one more piece of the puzzle: What do we do about the
weak
reference? After all, let's say the good ol' compiler comes around and yanksself
out from under you with a quick-release
. Because of that zeroing weak pointer, you now have a nil pointer running amok in your block. This can lead to it literally doing nothing, while you sit there and scratch your head wondering why. This has led to the invention of, what I will term, the weak-strong dance.J_mcnally's example is missing one crucial step in the dance, the "re-strongification" of your self pointer. But, why would we want to do that after we just went to all the trouble to avoid a retain cycle? It's because our strong copy of X isn't retained by the block, it's retained by the block's scope. In english, it means that our strong
self
will only deallocate once the end of the block has reached, thus guaranteeing not only a safe memory-cycle, but that it will not get deallocated out from under us. A proper fix looks like this:Yes it will lead to a retain cycle.
The workaround incase you care is