UINavigationController subclass leaks member variable memory

Hello community,

  I just encountered a pretty weird behavior when I subclass `UINavigationController` without overriding any initializers.

Simple Code:

import UIKit

class MyViewController: UINavigationController {
  
  let value: Int = {
    print("member init")
    return 3
  }()
}

let _ = MyViewController(rootViewController: UIViewController())

output is:

member init
member init

In fact any member variables declared in this subclass is initialized twice but deinitialized only once.
This phenomenon only appears when using `init(rootViewController:)`.

CMIW, It looks like Swift somehow treat this initializer as a designated initializer, rather than a convenience one.

Any Ideas?

Your analysis is correct. The problem is that UINavigationController's header file doesn't properly declare which initializers are designated and which are convenience. Fortunately, you're not the first to notice this; it's tracked by the UIKit folks as rdar://problem/27255526. I'll poke them about it.

Thanks for bringing it up!
Jordan

···

On Dec 13, 2017, at 23:05, 吴君恺 via swift-users <swift-users@swift.org> wrote:

Hello community,

  I just encountered a pretty weird behavior when I subclass `UINavigationController` without overriding any initializers.

Simple Code:

import UIKit

class MyViewController: UINavigationController {
  
  let value: Int = {
    print("member init")
    return 3
  }()
}

let _ = MyViewController(rootViewController: UIViewController())

output is:

member init
member init

In fact any member variables declared in this subclass is initialized twice but deinitialized only once.
This phenomenon only appears when using `init(rootViewController:)`.

CMIW, It looks like Swift somehow treat this initializer as a designated initializer, rather than a convenience one.

Any Ideas?

Thanks a lot, Jordan.

···

在 2017年12月15日,上午2:08,Jordan Rose <jordan_rose@apple.com> 写道:

On Dec 13, 2017, at 23:05, 吴君恺 via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

Hello community,

  I just encountered a pretty weird behavior when I subclass `UINavigationController` without overriding any initializers.

Simple Code:

import UIKit

class MyViewController: UINavigationController {
  
  let value: Int = {
    print("member init")
    return 3
  }()
}

let _ = MyViewController(rootViewController: UIViewController())

output is:

member init
member init

In fact any member variables declared in this subclass is initialized twice but deinitialized only once.
This phenomenon only appears when using `init(rootViewController:)`.

CMIW, It looks like Swift somehow treat this initializer as a designated initializer, rather than a convenience one.

Any Ideas?

Your analysis is correct. The problem is that UINavigationController's header file doesn't properly declare which initializers are designated and which are convenience. Fortunately, you're not the first to notice this; it's tracked by the UIKit folks as rdar://problem/27255526 <rdar://problem/27255526>. I'll poke them about it.

Thanks for bringing it up!
Jordan

Is this something that will get fixed in a new swift version? (it's not been fixed in Swift 4.2)