Reputation: 367
Swift can have Deinitializers (Like C++ Destructors) for Classes. When I am using a Non-Optional Instance of a Class (That is, var obj: Class
not var obj: Class?
), I am unable to see the message printed by the Deinitializer. However, when an Optional Instance of a Class is assigned to nil
, the Deinitializer message pops up. Even when a Non-Optional Instance of a Class is used, it would be automatically deallocated when the Reference Count gets over, right ? Then, Why is the deinitializer message not popping up for Non-Optional Instances ?
Example Code to reproduce this behavior:
class A: CustomStringConvertible
{
var value: Int
var description: String
{
get
{
"A (value = \(value))"
}
}
init(_ value: Int)
{
self.value = value
}
deinit
{
print("\(self) is being deinitialized !")
}
}
var a: A = A(5)
print(a)
var aOpt: A? = A(10)
print(aOpt!)
aOpt = nil
Output:
A (value = 5)
A (value = 10)
A (value = 10) is being deinitialized !
Upvotes: 2
Views: 707
Reputation: 73366
The deinitialization is managed via the swift ARC. To simplify: it is triggered for an object (not a variable) when there is no longer a valid reference to the object. This happens for example when setting an optional variable to nil
. But also by assigning another object to a non-optional variable. And also when variables are no longer in scope (e.g. exiting a function when the object is not returned).
The following adaptation of your code shows these different cases (see the comments for the details):
class A
{
var value: Int
init(_ value: Int)
{
self.value = value
print("A object with ivalue \(value) was initialized")
}
deinit
{
print("A object with value \(value) was deinitialized")
}
}
func test() {
var a: A = A(5) // (5) is initialized
let b = A(6) // (6) is initialized
a = b // no reference anymore to (5) so it is deinitialized
//a = nil // not allowed because it's not optional
var aOpt: A? = A(10) // (10) in intialized
aOpt = nil // no reference anymore to (10) so it is deinitialized
} // a dies, so no reference anymore to (6) which is deinitialized
test()
print ("This is the end")
I managed to get all the objects to be deinitialized before reaching the final print, simply by declaring them in a function body. This gives a tighter control on the variable lifecycles. But when you declare global or static variables, it's different, because the variables continue to exist until termination of a programme. Would my snippet run the test()
outside of the function, the object (6) would not be deinitialized, since it would still be still referenced by a variable.
And with Swift, once the programme is terminated, it's over. Unlike C++, there is no guarantee that the remaining objects are properly deinitialized: Swift gives back the the resources to the the system without individually deinitializing every object.
If this is a problem for you, the best is to avoid global variables as much as possible (this is in any case a good practice). And if you have to use them, make sure the the app has a single exit point that cleans the object properly.
Upvotes: 3