3

With a NSNotificationCenter block, I have to use [unowned self] to avoid a strong reference cycle:

NSNotificationCenter.defaultCenter()
    .addObserverForName(UIApplicationWillEnterForegroundNotification,
        object: nil,
        queue: nil,
        usingBlock: { [unowned self] (notification : NSNotification!) -> Void in
            self.add(123)
        })

However, in UIView.animateWithDuration, I do not have to use [unowned self]:

   UIView.animateWithDuration(0.5, animations: { () -> Void in
      self.someOutlet.alpha = 1.0
      self.someMethod()
   })

What's the difference?

TruMan1
  • 33,665
  • 59
  • 184
  • 335

2 Answers2

6

The only difference between the animation block and the notification center block is that the animation block is extremely short-lived—it is executed immediately and then released.

In both cases, the blocks will capture self; but only the NSNotificationCenter code is problematic because the notification center will hold a reference to the block indefinitely, since the notification can happen at any time.

Note that this is different than a circular reference. A circular reference is often created by an object holding a reference to a block that captures self, like this:

self.myBlock = {
   self.doSomething()
}

That circular reference means that self will never be deallocated. The notification center isn't a circular reference (since self doesn't hold a reference to the notification center), it's just a regular reference that will be held until the observer is removed.

John Gibb
  • 10,603
  • 2
  • 37
  • 48
1

The animations: () -> Void and completion: ((Bool) -> Void)? blocks for a UIView Animation do not retain a reference to self. This previous post is very informative on the topic

Do we need to use __weak self inside UIAnimationBlocks in ARC?


The notification block (NSNotification) -> Void does retain a reference to self, by passing it in as unowned in your case, it should not increment the retain count. I try to ensure I use either unowned, or weak, on any reference I pass into the closure. There is a great post about this found here http://krakendev.io/blog/weak-and-unowned-references-in-swift


But, I highly recommend staying away from using Notifications, especially with blocks, as there maybe a bug pointed out by this article, which was shocking when I read it.

http://sealedabstract.com/code/nsnotificationcenter-with-blocks-considered-harmful/

Community
  • 1
  • 1
AntonTheDev
  • 899
  • 6
  • 13
  • Whoa that's crazy, so it's only because of a Cocoa bug I have to do this? – TruMan1 May 24 '16 at 00:14
  • @TruMan1The answer I provided only highlighted an issue with the notification center. The true reason is that you want to avoid creating a strong reference cycle, I updated my answer to reflect that – AntonTheDev May 24 '16 at 02:13