Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A deinitializer is a special method invoked automatically by Swift immediately before an instance of a class, actor, or noncopyable type is deallocated from memory. It provides a deterministic execution block that runs just before the memory occupied by the instance is reclaimed.

Syntax

A deinitializer is declared using the deinit keyword. Unlike initializers or standard methods, it does not take parameters, requires no parentheses, and returns no value.
class StandardClass {
    deinit {
        // Execution block
    }
}

struct NoncopyableStruct: ~Copyable {
    deinit {
        // Execution block
    }
}

Core Mechanics and Rules

  • Supported Types: Deinitializers are available for reference types (class and actor) and noncopyable value types (struct and enum declared with ~Copyable). Standard copyable value types do not support deinitialization hooks.
  • Automatic Invocation: You cannot call a deinit method explicitly. The trigger mechanism depends on the type:
    • Reference Types: Automatic Reference Counting (ARC) triggers the deinitializer when an instance’s strong reference count drops to zero.
    • Noncopyable Types: The compiler injects the deinitializer call when the unique instance is destroyed at the end of its lifetime (e.g., falling out of scope). Explicitly consuming a value (e.g., let newOwner = consume oldOwner) transfers ownership; it does not trigger the deinitializer. The deinitializer only runs when the value is ultimately destroyed by its final owner.
  • Instance Validity and Isolation: During the execution of the deinit block, the instance remains initialized and its properties are accessible. For actor types, the deinitializer is synchronous and non-isolated. Because the actor’s reference count has dropped to zero—guaranteeing no other code can be executing concurrently on the actor—Swift explicitly permits accessing the actor’s actor-isolated stored properties within the deinitializer. However, calling actor-isolated methods or accessing actor-isolated computed properties remains strictly prohibited.
  • Single Declaration: A type can have at most one deinitializer.

Bypassing Deinitialization with discard

For noncopyable types, you can explicitly prevent the deinitializer from running by using the discard operator. Calling discard self inside a consuming method ends the instance’s lifetime and reclaims its memory without invoking the deinit block.
struct Resource: ~Copyable {
    deinit {
        print("Resource destroyed")
    }

    consuming func close() {
        // Ends lifetime and prevents deinit from executing
        discard self
    }
}

Inheritance and Chaining

In a class hierarchy, deinitialization propagates upwards from the subclass to the ultimate base class. Swift handles this chaining automatically.
  1. When a subclass instance is deallocated, the subclass’s deinit block executes first.
  2. Upon completion of the subclass’s deinit, the superclass’s deinit is called automatically.
  3. This upward delegation continues until the root base class is reached.
  4. A superclass deinitializer is guaranteed to execute, even if the subclass does not explicitly define its own deinit block.
class BaseClass {
    deinit {
        print("BaseClass deinit executed")
    }
}

class SubClass: BaseClass {
    deinit {
        print("SubClass deinit executed")
    }
}

var reference: SubClass? = SubClass()
reference = nil 

// Execution Order:
// 1. "SubClass deinit executed"
// 2. "BaseClass deinit executed"
Master Swift with Deep Grasping Methodology!Learn More