Object–Oriented Programming with Swift 2
上QQ阅读APP看书,第一时间看更新

Customizing deinitialization

We want to know when the instances of the Circle class will be removed from memory—that is, when the objects aren't referenced by any variable and the automatic reference count mechanism decides that they have to be removed from memory. Deinitializers are special parameterless class methods that are automatically executed just before the runtime destroys an instance of a given type. Thus, we can use them to add any code we want to run before the instance is destroyed. We cannot call a deinitializer; they are only available for the runtime.

The deinitializer is a special class method that uses the deinit keyword in its declaration. The declaration must be parameterless, and it cannot return a value.

The following lines declare a deinitializer within the body of the Circle class:

deinit {
    print("I'm destroying the Circle instance with a radius value of \(radius).")
}

The following lines show the new complete code for the Circle class:

class Circle {
    var radius: Double
    init(radius: Double)
    {
        print("I'm initializing a new Circle instance with a radius value of \(radius).")
        self.radius = radius
    }
    
    deinit {
        print("I'm destroying the Circle instance with a radius value of \(radius).")
    }
    
}

The code within the deinitilizer prints a message on the console indicating that the runtime will destroy a Circle instance with a specific radius value. This way, we will understand when the code within the deinitializer is executed.

The following lines create two instances of the Circle class named circleToDelete1 and circleToDelete2. Then, the next lines assign new instances to both variables; therefore, the reference count for both objects reaches 0, and the automatic reference counting mechanism destroys them. Before the destruction takes place, Swift executes the deinitialization code. Enter the following lines in the Playground after adding the code for the destructor to the Circle class:

var circleToDelete1 = Circle(radius: 25)
var circleToDelete2 = Circle(radius: 50)
circleToDelete1 = Circle(radius: 32)
circleToDelete2 = Circle(radius: 47)

We will see the following messages in the Playground, as shown in the screenshot that follows them:

I'm initializing a new Circle instance with a radius value of 25.0.
I'm initializing a new Circle instance with a radius value of 50.0.
I'm initializing a new Circle instance with a radius value of 32.0.
I'm destroying the Circle instance with a radius value of 25.0.
I'm initializing a new Circle instance with a radius value of 47.0.
I'm destroying the Circle instance with a radius value of 50.0.

The first two lines appear because we created instances of Circle, and Swift executed the initialization code. Then, we assigned the result of creating a new instance of the Circle class to the circleToDelete1 variable, and therefore, we removed the only existing reference to the instance with a radius value of 25.0. Swift printed a line that indicates that it initialized a new instance with a radius value of 32.0. After this line, Swift printed the line generated by the execution of the deinitializer of the Circle instance that had a radius value of 25.0.

Then, we assigned the result of creating a new instance of the Circle class to the circleToDelete2 variable, and therefore, we removed the only existing reference to the instance with a radius value of 50.0. Swift printed a line that indicates that it initialized a new instance with a radius value of 47.0. After this line, Swift printed the line generated by the execution of the deinitializer of the Circle instance that had a radius value of 50.0.

The following lines create an instance of the Circle class named circle3 and then assign a reference of this object to referenceToCircle3. Thus, the reference count to the object increases to 2. The next line assigns a new instance of the Circle class to circle3; therefore, the reference count for the object goes down from 2 to 1. As the referenceToCircle3 variable stills holds a reference to the Circle instance, Swift doesn't destroy the instance, and we don't see the results of the execution of the deinitializer. Note that the screenshot only displays the results of the execution of the initializer, and there is no execution for the deinitializer:

var circle3 = Circle(radius: 42)
var referenceToCircle3 = circle3
circle3 = Circle(radius: 84)