我可以在 deinit 中使用 didSet 吗?

Can I use didSet in deinit?

我在 class 中添加了一个 Timer 变量,并使用它的 didSet 观察器使旧值无效

var timer: Timer? {
    didSet { oldValue?.invalidate() }
}

deinit {
    timer = nil
}

我认为这足以在 class 被取消初始化时使计时器无效,但看起来 didSet 没有被调用。这是为什么?观察者在取消初始化期间是否不工作?

Let's put an answer here so we can close this off.

  • It seems that 属性 observers apparently do not 运行 during deinit. This seems parallel to the fact that 属性 observers do not 运行 during init, but unlike the latter, the former doesn't seem to be clearly documented anywhere.

  • You can work around this by semantic trickery, but don't! That seems like a bug (and I've filed it).

  • The original use case was not a very good one to begin with. Hiding invalidation of a timer in replacement sounds like a potential maintenance nightmare. Agreed that invalidation and replacement go together like ham and eggs, what I always do is write a method that invalidates and replaces, in that order, and funnel everything through that method. (This can be enforced if necessary, but I won't go into that.) That method can be called during deinit.

SUPPLEMENTARY NOTE: Watch out, when using a timer, for memory management issues! You can easily get yourself into a situation where deinit is never called, because you're retaining the timer but the timer is retaining you. You will then fail to invalidate the timer and your entire view controller will leak. You don't complain about that in your question, but it's a related matter so I thought I'd better flag it.