Skip to content

Instantly share code, notes, and snippets.

@jonathan-beebe
Created December 22, 2016 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathan-beebe/afc54e2c701c3a09a089afc3ac6cded9 to your computer and use it in GitHub Desktop.
Save jonathan-beebe/afc54e2c701c3a09a089afc3ac6cded9 to your computer and use it in GitHub Desktop.
Memory Leaks in iOS

Blocks that are added to a notification center

typeof(self) __weak weakSelf = self;
[[[EDFlux sharedInstance] budgetStore] addChangeObserverWithBlock:^(NSNotification* note) {
    [weakSelf doSomething];
}];
EDFlux.sharedInstance().budgetStore.addChangeObserverWithBlock({ [weak self] (notification) -> Void in
    self?.doSomething()
})

which simply forwards to

- (id<NSObject>)addChangeObserverWithBlock:(void (^)(NSNotification* note))block
{
    return [self.notificationCenter addObserverForName:kFluxStoreChangedEventName object:nil queue:nil usingBlock:block];
}

Block as DI property

Say we have a definition like this:

class MyClass {

    var callback:(() -> ())?
    
    ...
}

Defining a callback that captures self strongly will create a memory leak. There are two options:

weak

If the block might persist beyond the life of self then you can use [weak self] and treat self as an optional.

myInstance.callback = { [weak self] in
    self?.doSomething()
}

And of course you can use an if let or guard here

myInstance.callback = { [weak self] in
    guard let strongSelf = self else { return }
    strongSelf.doSomething()
}

unowned

If you know that self will always be around during the life of the block then you can use [unowned self] so it is not captured strongly, but it also is not optional. Accessing self like this if self has been deallocated will crash the app.

myInstance.callback = { [unowned self] in
    self.doSomething()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment