Which one happens first?
deinit
Without 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