I finally figured out weakSelf and strongSelf

One problem with using blocks and asynchronous dispatch is that you can get into a retain cycle – the block can retain ‘self’, sometimes in mysterious ways. For instance, if you reference an ivar directly, what appears in the code is ‘theIvar’, the compiler generates ‘self->theIvar’. Thus, ‘self’, as a strong variable, is retained, and the queue retains the block, and the object retains the queue.

Apple recommends first assigning ‘self’ into a weak automatic variable, then referencing that in a block (see 1). Since the block captures the variable along with its decorators (i.e. weak qualifier), there is no strong reference to ‘self’, and the object can get dealloced, and at that moment the weak captured variable turns to nil.

__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
[weakSelf doSomething];
} );

Thinking about this, it occurred to me that ‘weakSelf’ might turn to nil in the middle of ‘doSomething’, but after a few posts on the xcode list, I was given a reference to a clang document that explicitly states that any object within an expression is retained for the complete expression, and only released thereafter (see 2). Whew!

But how about:

__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
[weakSelf doSomething];
[weakSelf doSomethingElse];
} );

Well, in this case, its possible for ‘weakSelf’ to be non-nil for the first method, but not for the second. Hmmm – the above is a simple example, most real code would get much more complex with other usages of ‘weakSelf’.

Apple calls this second example ‘non-trivial’ (see 1), and does what first seems like a bizarre set of steps: first create the ‘weakSelf’ object, then assign that to a ‘strongSelf':

__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
__typeof__(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doSomethingElse];
} );

or in Swift:

dispatch_async(dispatch_get_main_queue()) { [weak self] in
if let strongSelf = self {
//…
}
}
// See “Resolving Strong Reference Cycles for Closures” in The Swift Programming Language

I looked and looked at this trying to reason it out (guess I’m just slow). Finally, the light bulb lit, and I figured it out! When the block runs, it’s only captured ‘weakSelf’. At the instant the block starts up, ‘weakSelf’ is either ‘self’, or it’s nil. Your code (as Apple’s example does) can test to see if ‘strongSelf’ is set, and if so you can use ‘strongSelf->theIvar’ or the more normal ‘strongSelf.someProperty’ (the latter works fine with nil messaging, the former will crash if ‘strongSelf’ is nil).

If ‘weakSelf’ is equal to ‘self’, then ‘strongSelf’ retains it, and it stays retained until the block returns, when its released. It’s all or nothing.

I felt really good finally getting this, and its making my coding of blocks much easier.

NOTE:

If you’re puzzled by the use of __typeof__(self), it’s a non-standard clang macro that turns into the class of the parenthesized object, and was taken from GCC. The nice thing about using it is that you can make this line a Code Snippet (mine is called ‘WeakSelf’), and you don’t have to continually adjust the class type.

1) “Programming With ARC Release Notes, search for “For non-trivial cycles, however, you should use”

2) http://clang.llvm.org/docs/AutomaticReferenceCounting.html :

For __weak objects, the current pointee is retained and then released at the end of the current full-expression. This must execute atomically with respect to assignments and to the final release of the pointee.

About these ads

22 thoughts on “I finally figured out weakSelf and strongSelf

  1. David, This is awesome & the website is awesome, Everything is so cool. You make the website so amazing. I will decorate my wordpress later, mine is plain.

    • The logic is the same. When the next level deep is created it captures, and then when executed the same issues apply. It should be no different that the first capture. Note that a block that creates a block is processed as the first block created, then executed, and only when that code executes is the second block created. Obviously you’d want to capture references one level above you and not ‘self’ from the top level no block code.

  2. How about an example when there is a call back to main queue from dispatch like this:

    __weak typeof (self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    typeof (self)strongSelf = weakSelf;
    [strongSelf doTheJob];

    dispatch_async(dispatch_get_main_queue(), ^{
    //[strongSelf refreshUI] or [weakSelf refreshUI] or [self refreshUI]
    }
    });

    Which call is right?

    Thanks!

    • So lets look at the final section:

      typeof (self)strongSelf = weakSelf;
      // At the time of the above assignment statement, weakSelf could be nil, meaning strongSelf would be nil too.
      // NOTE: strongSelf is not going to go away now (if it was not nil).
      // Actually, I believe even if you use weakSelf in a method call, it gets retained for the life of that message so in this case weakSelf is probably not needed
      // weakSelf is still valid, as strongSelf is keeping it alive in all cases
      [strongSelf doTheJob];
      // strongSelf could go away now if not referenced further. If it had been valid, but the original "self" is no longer around, then weakSelf would go to nil

      // You could add a test in this block too, just after the assignment to strongSelf: if(strongSelf) { [strongSelf doTheJob]; dispatch_async...as below

      dispatch_async(dispatch_get_main_queue(), ^{
      // You want a weak reference here so as to not overly keep "self" alive
      // standard format would be to re-use your above construct
      typeof (self)strongSelf = weakSelf;
      [strongSelf refreshUI];
      }

  3. Fantastic article, and I have used your format quite a bit by now. In a project I am working on at the moment with other people, I’m seeing the following being used:

    __block typeof(&*self) bSelf = self;

    And then inside the blocks it just uses bSelf.

    How does that compare to what you are recommending here?

    Thanks for any clarification,
    Erik

    • Hmmm not quite sure why &* is needed, but this is of course different. The __block will strongly retain self for the scope of self. What I have is a series of auto variables that either are strong with limited scope, or weak. Note that Xcode 5.1 now issues a warning if you use a weak variable more than once, which helps to point out places where you haven’t properly annotated a variable. In my examples, at any point the weak variable might be nil, and a strong variable initialized to nil is nil, and so will start and end that way, and nothing “bad” will happen. You just cannot access an ivar with a nil self, as that results in an offset off 0 which will cause an exception.

  4. Thanks for this clear explanation. As far as I can tell, it is only necessary to do this when `self` holds a strong reference to the block. Otherwise there shouldn’t be an issue with retain cycles. Is that correct?

    • Normally you will get a warning in Xcode when you do something that’s likely to create a retain cycle, but not always. The big no-no is having a strong block ivar, creating a block that references self, then saving that block in the ivar.

      There is no simple yes/no to your question – it gets tricky when blocks get saved and passed around – you have to think about it in those cases.

  5. Yeah I’ve seen that warning on occasion. In the case you describe, is the retain cycle happening on the strong ivar though or on self? The reference in both cases is pointing to the ivar, not to self. Unless ARC actually increases the retain count for self when you access its strong ivars?

    • The issue is that once the block retains the block owner, there is no way to release the owning object, thus the block never gets released during dealloc. This retain cycle can only be solved by (somehow) having some other object release the block first. This is the same classic retain cycle that you see when a delegate object retains the delegate.

      • Well, if `self` isn’t retaining the block, then the block will get dealloc’d when it goes out of scope, and the reference count for the retained owner within the block will get decremented. So as far as I can tell, the retain cycle can only happen when the block is strongly referenced by something the block is strongly referencing. In other words, if you have a `self.myBlock` ivar or you store the block in an `NSOperation` ivar, or something like that. Unless I am misunderstanding…

    • Jamie, when you reference an ivar, there is an implicit reference to `self` (e.g. referencing some ivar called `x` is actually equivalent to referencing `self->x`).

  6. Hey Guys,
    Just wondering, if we do this, shouldn’t we do the same thing with UIView:animationWithBlock… ? because a block is a block, isn’t it?

    It says another thing related to blocks.

    http://prntscr.com/49rfs2

    Warms Regards,
    Fernando

    • No, because the block will get executed immediately, and the view cannot get released before the block completes. The whole issue with retaining self has to do with creating a block that persists – its saved in an ivar until such time as its needed. Blocks that are created, run, then released do not cause problems.

  7. Pingback: 1Password App Extension for iOS 8 | AskmeBoy

  8. Another great example:

    dispatch_async {

    [strongself callAMethod];
    }

    – (void)callAMethod
    {
    self.doStuf…
    }

    What is with self in a “callAMethod” method? Does is cause a retain cycle or is this “self” in context of dispatch_async and is actually “strongself” ?

    • The last code block has been reproduced in Swift. Its actually easier to understand and write too!

      Here is a bit of code I used to test it (you can try it out in a test project):

      class Foo : NSObject {
      var name: String?
      var title: String?
      }

      var foo: Foo! = Foo()
      foo.name = “Me”
      foo.title = “Head Cheese”

      var closure: () -> Void = { [weak foo] in
      if let strongFoo = foo {
      println(“name=\(foo?.name)”)
      println(“title=\(foo?.title)”)
      }
      }

      closure()
      foo = nil
      closure()

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s