class A {
var b: B
init(b: B) {
self.b = b
}
deinit {
print(" Destroying A")
}
}
class B {
weak var a: A?
deinit {
print(" Destroying B")
}
}
func setup(_ a: inout A?, _ b: inout B?) {
b = B()
a = A(b: b!)
b?.a = a
}
var bravo: B?
var alpha: A?
setup(&alpha, &bravo)
bravo = nil
alpha = nil
// OUTPUT:
// " Destroying A"
// " Destroying B"
I've tried all permutations of setting alpha and bravo to nil, and yet I cannot get bravo to deinit before alpha. Based on my brief experiment in Swift Playgrounds, alpha always gets deinit before bravo. Can someone please explain why?
I know this has to do with ARC, but I thought if bravo = nil, then isn't the value of alpha.b also nil? If so, then wouldn't it be safe to deinit bravo safely before alpha?
I'd love to know what the retain counts are on each of these instances over time.
Not sure I understood the question, but I see this as quite straight forward application of ARC rules. After the line
you have
bravo(thebravoitself, and its referencealpha.b)alphaitself), and 1 weak (bravo.a) reference to the objectalphaNow you set
bravo = nil, removing 1 strong reference, but the other strong reference remains, sodeinitis not called, based on rule:Next you set
alpha = nil. That's deleting its only strong reference, hence based on ruleA can be deallocated immediately. Also important to remember that
In other words, the order of operations is:
alpha = nilnildeinitis calledSo now, that
alphais deleted, no references of any kind are left forbravo, and hence itsdeinitcan be called.