swiftautomatic-ref-countingdestructordeallocdeinit

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?


Solution

  • 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).