3

I've created new app from macOS Cocoa App template. The only change I've made is added deinit in NSViewController. So now it looks like this(complete code):

import Cocoa

class ViewController: NSViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    func doSomething()
    {
        var a = 10
        a = a + 1
        print(a)
    }

    deinit {
        doSomething()
        print("deinit called")
    }
}

Why I don't see deinit call? I've searched number of questions here, but couldn't find answer, as I don't have any retain cycle.

Pablo
  • 28,133
  • 34
  • 125
  • 215
  • How many `viewControllers` you have in the app? Are you dismissing this viewController or Poping incase it was pushed on `navigationController`? Is this the only `ViewController` you have in your app? – Kamran Oct 28 '18 at 13:29
  • There is no navigation controller. I would like to emphasise that this is macOS Cocoa boilerplate app. There is window controller, which is embedding view controller. Only embedded view controller is subclassed. I don't pop or dismiss, instead just closing app and expecting to see "deinit called" in output window. – Pablo Oct 28 '18 at 14:28

2 Answers2

1

As Tobi says in his answer, deinit gets called right before an object is deallocated.

An object gets deallocated when there are no longer any strong references to it. (Nobody owns the object any more.)

In order to answer your specific question you need to look at how your view controller is created an who owns it.

I haven't done much Mac development in a while, so I'm kinda rusty on view controller lifecycle, but here's my recollection of how it works:

If you only have one app window, it is the view controller's owner, and the window never gets closed, that means the view controller will never get deallocated.

If you quit the app I don't think the system tears down your window hierarchy before terminating the app (unless you're app is a document-based app, in which case the app will be told to close all of it's document windows before quitting.)

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Theoretically I understand view controller would get deallocated when there is no strong reference to it. But I would like to know details based on boilerplate code, what is holding it. I have one NSWindow, with its VC(but I am not subclassing it). It embeds NSView, with view controller, which is subclassed in boilerplate, where I wrote `deinit`. I have model object initialised in view controller and I have `deinit` also in my model object, to clean up stuff. Since my view controller is never gets deallocated, the routines in my model class `deinit` also not called. – Pablo Oct 28 '18 at 15:03
  • It looks to me like the boilerplate code is incomplete. I created a boilerplate Mac Cocoa app and found the same thing you did: A view controller gets created when you launch the app, but never gets deallocated. As mentioned, I'm rusty with Mac OS. You might want to post your test project (with your deinit call and with logging) to github, include a link here, and see if somebody who's actively doing Mac development can chime in. – Duncan C Oct 28 '18 at 20:31
0

A deinitializer is called immediately before a class instance is deallocated.

Altho your question is not clear to me.

But the usual reason for failure to trigger deinit when expected is that you have a retain cycle that prevents your view controller from going out of existence.

Sometimes the reason is that your expectation that the view controller would be destroyed under the circumstances is incorrect.

But assuming it is correct, a retain cycle is the reason.

another suggestion is to use Hierarchies Debug.

answer those questions for your self.

is this the root UIViewController ?

is it dismissed properly ?

Mohmmad S
  • 5,001
  • 4
  • 18
  • 50
  • It is not iOS related question, but macOS cocoa app. The question is why `deinit` of my view controller not called? If there is retain cycle, where is it in boilerplate code? There is NSWindow(with not subclassed view controller) and embedded NSView with subclassed view controller, where I added `deinit`. I just quit application and expect `deinit` of view controller to be called. I guess it's not root `NSViewController`, since there is also `NSWindow` with its VC. – Pablo Oct 28 '18 at 15:08
  • i haven't done mac development but theoretically the ViewController is not dismissed, try to add a breakpoint inside of it and dismiss it form your application check if it triggers – Mohmmad S Oct 28 '18 at 15:11