1

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?

Top-Master
  • 7,611
  • 5
  • 39
  • 71

2 Answers2

2

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.
    }
    

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

Top-Master
  • 7,611
  • 5
  • 39
  • 71
  • 1
    @Rob let's say MyClass itself avoided using any `autorelease` feature and the `ObjC` classes it uses avoid it too, could it still be put into pool together with another class that has such use? (I don't mean member variable, that would be a yes, of course) – Top-Master Aug 10 '21 at 20:22
  • 2
    The autoreleasepool is only relevant for autorelease objects. If you have no autorelease objects, then they don’t go into any pool. They are deallocated as soon as there are no more strong references. The motivating idea behind reference counting is to ensure a deterministic deallocation of objects, rather than giving the garbage collector the discretion of when this happens. Now, there are some isolated classes that do their own cacheing (e.g., `UIImage(named:)`), but that’s a separate question. – Rob Aug 10 '21 at 20:36
1

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.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Edited my answer and applied our comments (I think, maybe little before your post here), but when I accept that answer, I am actually accepting your suggestions (I would directly accept this if it would mention `autorelease`-pool and other details). – Top-Master Aug 10 '21 at 21:22