Besides being a pillar for any great modern society, learning to give back what one gets is also one of the best practices in the mobile ecosystem. Why?

Our mobile devices are little monster of power, but their power is limited. So using it in the most efficient way is paramount. Efficiency can be achieved in several ways, from designing state-of-the-art hardware to writing platform-aware software. As mobile software developers, we can mostly contribute to the latter, and we can do so by giving back to the system all the resources we previously got and that we do not need anymore.

So, few years ago, when Apple had not yet revealed ARC, it was normal to see code similar to this

  NSString *name = [[NSString alloc] init];
  [self doSomethingWithString: name];
  [name release];

where you would first ask the OS for some memory where to store the string, perform some actions with it and when finished, you would release the memory given to you. The OS would manage the memory for you at its best, but you still needed to be a good memory management citizen and give back the resources you didn’t need anymore.

When ARC was released, Apple gave developers a huge help in being good citizens: unused resources would be claimed by the OS automatically. So the above code became

  NSString *name = [[NSString alloc] init];
  [self doSomethingWithString: name];
  let name = NSString()
  doSomethingWithString(name)

No need to release anything anymore. Kudos for Apple :heart:

But one basic principle stayed the same, even till today Swifty world: if you need to keep a resource around, you must create and hold a strong reference to it. As long as you do that, no OS will take it away from you (well, besides those cases where your app would be terminated by the OS itself).
With this basic rule in mind, let’s make the whole story more interesting by mixing memory management with Swift closures (a.k.a blocks in Objective-C).

In the following code, a method on a UIViewController subclass is used as a delegate callback after carrying out some work. Very common scenario when developing UIKit-based apps.

  func controllerDidSomeWork() {
      dismiss(animated: true) {
          self.postDismissCleanUp()
      }
  }

Inside the method the view controller attempts to dismiss its presented view controller by calling dismiss(animated:completion:) and passing a closure needed for some cleanup. The closure knows the basic principle I mentioned above and so is keeping a strong reference to self through the call to postDismissCleanUp.

What I have seen in several code bases I worked on is the following version of the previous snippet

  func controllerDidSomeWork() {
      dismiss(animated: true) { [weak self] in
          self?.postDismissCleanUp()
      }
  }

Here the programmer took a safe approach to the problem of memory management with closures, and decided to avoid a retain cycle by using a capture list. In this list, the closure is being instructed to create a weak reference to self, rather than a strong one like it would normally do. That capture list transforms the type of self in the scope of the closure from UIViewController to UIViewController? and that explain the use of self?.

That weakification of self is absolutely not needed if the only reason is to prevent a retain cycle. It’s purely defensive programming. If not paranoia programming.

So when is it ok to write [weak self] in the capture list of a closure? Answer is pretty easy. If self holds a strong reference to the closure either directly or indirectly through other objects, then you have to weakify it like in the following snippet:

  class RetainingViewController : UIViewController {
      // self retains its closure ivar
      var cleanUpBlock: (() -> Void)?

      func controllerDidSomeWork() {          
          cleanUpBlock = { [weak self] in
              // the closure holds a weak reference to self
              self.postDismissCleanUp()
          }
          dismiss(animated: true, completion: cleanUpBlock)
      }

      func postDismissCleanUp() {
          print("Clean up work")
      }
  }

There is another reason though where you would want to weakify self in a closure. That reason has nothing to do with memory management and it is purely behavioral. A classic example is when performing an asynchronous network call as part of the lifetime of a view controller, like when you go to a screen displaying data which must be fetched from a remote server.
In that case you would create a view controller, present it, enqueue a network request and finally inform the user with a loading indicator. If the user leaves the screen before the network sends back the data, when this finally arrives you want to do nothing with it. The view controller is not on screen anymore so why bother?
Weakifying the controller would let you discard that data while a strong reference would keep the controller around even if the user has already left the screen. And this can be the source of some unexpected bugs.