Top-Master
Top-Master

Reputation: 8826

When is `deinit` exactly called? (in Swift)

When is deinit exactly called?

Is it like C++ guaranteed to be called when last reference gets out of scope (by return, throw or exit)?

Or is Swift using Garbage-Collector?

Upvotes: 3

Views: 4303

Answers (2)

Top-Master
Top-Master

Reputation: 8826

The deinit is intended to release resources (such as freeing memory that is not under ARC).

(Thanks to Martin and Rob's input, we can conclude below)

When is deinit called?

Usually, when last strong-reference gets out of scope, deinit is called instantly (then deallocation happens).

But:

  1. If affected by autorelease feature (which has conditions), deinit is called significantly later, long after last reference gets out of scope (when autorelease pool is drained).
  2. Or when App is terminating, deinit is guaranteed to never get called !! (if deinit was not already called).
  3. Also in extremely common cases, deinit is called before strong-ref-variable's scope ends:
    • In Swift unlike other languages, when we set a weak-reference equal to a strong-reference, it could result to nil (which is absolutely allowed by Swift).

    • This happens if compiler detects that the remaining lines of scope, have NOT any strong-reference.

    • Possible workaround is using withExtendedLifetime(_:_:) global-method / function, like:

    withExtendedLifetime(myStrongRefVariable) {
        // Do something that only needs a non-nil weak reference.
    }
    

Note that deinit may be skipped if related init throws at the right/wrong moment, see: https://forums.swift.org/t/deinit-and-throwing-initializers/38871

Is it like C++ destructor?

There is no equivalent of a C++ destructor in ObjC or Swift.

(Objective-C++ object's destructor (dealloc) are called during program termination, because that is required by C++ spec, but that's all and else Obj-C++'s dealloc behavior is almost same as deinit.)

Is Swift using Garbage-Collector?

No, but whenever autorelease feature affects objects, the deinit can be postponed (till autorelease-pool is drained, as mentioned above).

Upvotes: 3

Rob
Rob

Reputation: 438417

You asked:

When is deinit called?

In short, for reference types, an object is deinitialized when the last strong reference is removed.

So, it is often not a question of any particular variable, but rather a question of all of the references, and it is deinitialized when the last strong reference is removed, right before it is deallocated. See The Swift Programming Language, Deinitialization and Automatic Reference Counting.

You then asked:

Or is Swift using Garbage-Collector?

Swift does not use garbage collection. There used to be garbage collection (back in the early Objective-C days, for macOS targets), but that has long been deprecated and was replaced with a reference counting system, later simplified with the introduction of ARC (automatic reference counting). But Swift has never implemented garbage collection.

Upvotes: 2

Related Questions