Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Demo that retaining self in a NotificationCenter observer block leads to a reference cycle you have to break manually.
// Paste into a macOS playground in Xcode and run.
// Deleting line 46 "c?.stopObserving()" triggers the assertion because
// the reference cycle caused by retaining self in the observer block is never broken.
import Foundation
let myNotification = NSNotification.Name(rawValue: "myNotification")
var cHasBeenDeallocated = false
class C {
var observer: NSObjectProtocol?
init() {
deinit {
cHasBeenDeallocated = true
func startObserving() {
print("Starting listening to notification") = NotificationCenter.default.addObserver(forName: myNotification, object: nil, queue: nil) { notification in
print("- Received notification:", notification)
print("- Retaining self in notification block:", self)
func stopObserving() {
if let observer = {
print("Stopping listening to notification")
NotificationCenter.default.removeObserver(observer) = nil
var c: C? = C() myNotification, object: nil)
// Delete this line to trigger the assertion. deinit is never called because we created a reference cycle.
c = nil
// If the assertion is triggered, it means we have a reference cycle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment