This blog entry shows how to use snippets in Xcode to avoid retain cycles when working with asynchronous blocks. We use the weakSelf and strongSelf paradigm that Apple’s engineers recommend as a best practice in Objective-C.

Why weakSelf And strongSelf?

 
Nowadays a great many apps perform asynchronous operations using GCD blocks. For example, if you’ve ever done a fetch over a network you may have used asynchronous AFNetworking callback blocks or Apple’s native session-based asynchronous blocks. Apple recommends using a weak variable to reference self whenever we perform asynchronous operations in order to prevent retain cycles. Okay…but why?

First, some background. Remember that a block captures variables within its scope along with their qualifiers. That means if we reference self inside a block (i.e., a variable that’s intrinsically __strong), the block will hold onto it strongly. Similarly, if we reference a __weak variable in a block, the block will capture the weak variable, uh, weakly. 🙂

So what happens when self has a strong reference to a block, and that block in turn contains a strong reference to self? We have two objects in a cycle referencing each other strongly, and therefore we’ve got a retain cycle. Bad programmer! No cookie!

We need a solution in order to avoid nasty memory leaks. Fortunately there’s an easy answer, and it’s to simply use a weak reference to self. Now we can use weakSelf everywhere within our asynchronous block, like so:

    // your code

    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf doThis];
        [weakSelf doThat];
        [Manager.sharedInstance updateSuccessCount];
    });

    // more code

 
This breaks the retain cycle—so it’s better then using self—and in fact it’d be the ideal solution if we had only one single message to weakSelf. But, sadly, we have more than one message inside the block. In all other cases this is a naïve solution for reasons we’ll delve into next.

Basically we forgot something fundamental about how Clang and ARC work. That is, according to Clang’s documentation it’s possible that weakSelf can get automatically nilled after [weakSelf doThis]before [weakSelf doThat] is ever called—because Clang may decide to re-evaluate object retention on a statement-by-statement basis. Further, even if weakSelf is nil for both of those methods, we’ll still have the side effect of calling [Manager.sharedInstance updateSuccessCount] no matter what. Ack!

We want all the calls to weakSelf (and everything else) to succeed or fail as a group. What do we do?

The best solution is to modify our code fragment above. Notice that here we add a __strong reference to a strongSelf variable, but we only create that reference if weakSelf actually exists (this is critical according to Apple engineers we spoke to). Because strongSelf is strong it will live through the entirety of the block body and yet we didn’t create a circular reference to self either. Huzzah, the best of both worlds!

    // your code

    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        if (weakSelf) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            [strongSelf doThis];
            [strongSelf doThat];
            [Manager.sharedInstance updateSuccessCount];
        }
    });

    // more code

 
Great, we completely solved our circular reference problem! But that’s a lot of boilerplate code to remember and type. Fortunately, Xcode snippets can save us. But what the heck is a “snippet”?

Xcode Snippets FTW

 
Let’s start with a little background about Xcode snippets. Snippets are little chunks of code that you can create once in Xcode and then automatically reuse later by simply typing a completion shortcut. In fact, Xcode already provides a variety of snippets “out of the box”.

For example, if you’re inside an Objective-C method and you type dispatch_once you’ll see Xcode offer to replace your typing with a snippet. That’s because Xcode provides a snippet whose completion shortcut is “dispatch_once”. Handy!

The best part of this is we can define our own custom snippets and share them.

With no further ado, I present to you “Declare WeakSelf” and “Declare StrongSelf Conditionally” (snippets.zip).

The first snippet, “Declare WeakSelf”, is used before you invoke an asynchronous operation. It’s completion shortcut is “weak”, so if you start typing “weak” then Xcode will ask if you want to autocomplete a snippet of code that creates a weak reference to self.

The second snippet, “Declare StrongSelf Conditionally”, is used within your asynchronous block. It should be the first line you type in that block; just type “strong” and Xcode will offer to autocomplete it for you.

This animated GIF illustrates how to use the snippets.

Snippets in action!

Installation

 
Installation is pretty easy.

  1. Quit Xcode if it’s running.
  2. Download “snippets.zip” and decompress the file.
  3. Switch to Finder and hit ⌘+Shift+G, then enter ~/Library/Developer/Xcode/UserData/ into the text field, then hit Return. This will open a folder in Finder where you’ll install the snippets.
  4. Look for a folder called CodeSnippets in the folder you just opened. If you don’t already have a CodeSnippets folder, then create one (uppercase/lowercase is important).
  5. Using Finder, drag and drop the two uncompressed snippet files files into the CodeSnippets folder.
  6. Restart Xcode and you’re done.

That’s it! I hope this information and snippets are useful for you. Happy coding!

Bonus: Pro Tip

 
You do not need to use weakSelf and strongSelf when you’re performing UIView animations. UIView animations, while asynchronous, can safely use self without creating a retain loop. This is because self is not keeping a reference to the animation block when you invoke UIView’s -animateWithDuration:, so you don’t need to use weakSelf within the block. In other words, there’s no retain cycle between the inline block and self. Generally speaking, all other async operations should use weakSelf/strongSelf.

 

9 Responses to Avoiding ObjC Retain Cycles With weakSelf and strongSelf — The Easy Way

  1. Richard says:

    Is the check for weakSelf’s existence necessary? According to this article (http://www.informit.com/articles/article.aspx?p=2207347), it seems like creating a strongSelf reference with the __typeof__(self) statement is sufficient to ensure that self exists.

    The article:
    “If self still exists when the block starts to execute and hasn’t fallen back to nil, this next line ensures it persists throughout the block’s execution lifetime.”

    • Justin says:

      The short answer is, “yes”, the check for if (weakSelf) is necessary. The long answer is, “it depends”. Here’s why.

      There’s a good chance in any reasonably complex block that you’ll be sending messages to other objects besides weakSelf. However, if weakSelf is nil you generally don’t want the side effect of sending a bunch of messages to those other objects. Wrapping everything in a check for a nil weakSelf makes sure everything happens as a group, or not at all. For example:


      if (weakSelf) {
      [weakSelf doSomething];
      [someOtherObject doSomethingBecauseWeakSelfDidSomething]; // should only ever happen if weakSelf is not nil!
      }

      So in summary, it’s safest to simply always use if (weakSelf) { ... } in case you have messages to other objects in the same block, or might add messages to other objects in the future.

      • Maniac says:

        Wouldn’t it be better to check if the strongSelf is not nil after creating it?
        For my understanding weakSelf could get nil after the check

  2. What if the [strongSelf doThis] method also references a self.

    • Justin says:

      ARC will correctly handle memory management for the -doThis method (and all other methods including those that reference self).

  3. Tohnes says:

    Probably the best (concise & easy to understand) post I’ve read on weakSelf / strongSelf. Thanks!

  4. mach7 says:

    Probably the best (concise & easy to understand) post I’ve read on weakSelf / strongSelf. Thanks!
    ===========
    +1

  5. Shashank says:

    I got the concept of weakSelf, but why strongSelf is required? Can’t I work with weakSelf only?

    • Justin says:

      The idea is to grab a strong reference at the beginning of the block and hang onto it for the duration of the block. Otherwise, the weakSelf can go away (become nil) at any time within the block, which would be bad if your block is only partway complete.

Leave a Reply

Your email address will not be published. Required fields are marked *