Which one happens first?
deinitWithout looking at the documentation, nor implementation...
Only one order makes sense: nilling has to come first.
If deinitialization would start before nilling weak references ARC would suffer the good old resurrection problem (retaining an object that is in the process of being deallocated). That is not the case.
Here's my mental model of object destruction (again, not from the documentation, this can differ from real world):
deinit chain is called, possibly calling through to objc base classes deallocStep 1 through 4 happen atomically with regards to other threads potentially taking new strong references to the object.
Zeroing weak variable happens first. deinit happens later. At least in current implementation (Xcode 6.1, Swift 1.1) This is a result of observation of specific implementation, and I don't know how it is actually defined by the authors... If you have explicit source, please comment or answer.
There's also a related discussion in ADC forum.
Test code Avoid Playground when testing this to get correct lifecycle behaviour.
class AAA {
func test() {
}
}
var a1 = nil as AAA?
weak var a2 = nil as AAA?
class BBB: AAA {
var data = "Here be dragons."
override func test() {
println("test() called and a2 is now \(a2).")
}
deinit {
println("deinit called and a2 is now \(a2).")
}
}
a1 = BBB()
a2 = a1
a2!.test()
a1 = nil
Result:
test() called and a2 is now Optional(weak_deinit_order_comparison.BBB).
deinit called and a2 is now nil.
Then, the weak variable becomes nil before the deinit to be called.
This pre-nilling is applied equally to unowned objects. Unowned object will become inaccessible at the point of deist just like weak, and trial to access unowned object at the deinit will crash the app.
If you assign self to a weak var variable in deinit, it will become nil immediately. (Xcode Version 6.3.2 (6D2105))
class Foo {
init() {
}
deinit {
var a = self
weak var b = self
unowned var c = self
let d = Unmanaged.passUnretained(self)
println(a) // prints `Foo`.
println(b) // prints `nil`.
// println(c) // crashes.
println(d.takeUnretainedValue()) // prints `Foo`.
}
}
var f = Foo() as Foo?
f = nil
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With