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 !
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):
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.