Here is a modified code from the documentation example https://www.swift.org/documentation/server/guides/memory-leaks-and-usage.html#troubleshooting :
class ViewController: UIViewController {
var closure: () -> Void = { () }
public func doNothing() {}
public func doSomethingThatLeaks() {
self.closure = {
// This will leak as it'll create a permanent reference cycle:
//
// self -> self.closure -> self
self.doNothing()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Memory leak example:
doSomethingThatLeaks()
// Abandoned memory example:
// NotificationCenter.default.addObserver(forName: .init("Abandoned"), object: nil, queue: nil) { _ in
// print("\(self)")
// }
}
deinit {
print(#function, Self.self)
}
}
If you place it, for example, in a navigation controller, do a push-pop several times, deinit will not be printed.
But if you look in the Debug Memory Graph, it will not even show that there is a strong reference to this controller:
Only if you manually select:
You can see that it is held by the closure context, which it holds:
This is definitely not abandoned memory (like the commented piece of the code example), but it is not shown either in the Debug Memory Graph or in Instruments Leaks.
Why?