0

I can't figure out why a UIViewController instantiated with UIStoryboard.instantiateViewController does not deinit when initalized in a unit test

Here's the code that I expect to deinit but does not:

func testDoesNotDeinit() throws {
    var strongViewController: ViewController? =
        UIStoryboard(
            name: "Main",
            bundle: Bundle(for: ViewController.self)
        )
        .instantiateViewController(withIdentifier: "ViewController") as! ViewController

    print("set nil")
    strongViewController = nil
    print("post set nil")
}

The result is:

set nil
post set nil
*** deinit *** // From deinit {} function in UIViewController

When the UIViewController is initialized programmatically it will deinitialize properly

func testDoesDeinit() throws {
    var strongViewController: ViewController? = ViewController()

    XCTAssertNotNil(strongViewController)
    print("set nil")
    strongViewController = nil
    print("post set nil")
    XCTAssertNil(strongViewController)
}

with result:

set nil
*** deinit *** // From deinit {} function in UIViewController
post set nil

Any ideas?

wyu
  • 1,793
  • 17
  • 33
  • When I tried with a sample vc, both are deallocated and called `deinit`. It can be depend on your subviews and their references in *Main* storyboard. (as reference to [this](https://stackoverflow.com/a/26131792/3835963) answer.) – Omer Faruk Ozturk Jul 22 '20 at 06:25

1 Answers1

0

I set a breakpoint at print("post set nil") and inspected the memory graph at that point in time. I saw that the VC is being retained by an instance of UIStoryboardScene:

enter image description here

UIStoryboardScene seems to be a private API. The only thing I can find about it is this header. This is probably an implementation detail of instantiateViewController.

Sweeper
  • 213,210
  • 22
  • 193
  • 313