UINavigationController子类的便捷初始化使子类常量初始化两次

我有UINavigationControllerUITableViewController子类。

为了初始化子类,我决定使用一些convenience init方法来调用超类的一些指定的初始化器。 此外,每个子类都有一些let常量:

 let someValue: SomeClass = SomeClass() 

通过调用其新创建的convenience init方法成功初始化每个类。

问题是let常量在UINavigationController子类中被初始化为TWICE

 import UIKit import PlaygroundSupport final class Navigation: UINavigationController { convenience init(anyObject: Any) { self.init(rootViewController: UIViewController()) } let service = Constant("Constant Initialization -> Navigation") } final class Table: UITableViewController { convenience init(anyObject: Any) { self.init(style: .plain) } let service = Constant("Constant Initialization -> Table") } class Constant: NSObject { init(_ string: String) { super.init() debugPrint(string) } } Navigation(anyObject: NSNull()) Table(anyObject: NSNull()) 

我们是否允许使用上面的convenience init ? 为什么?

为什么这两种情况下的convenience init行为不同?

检查: 版本8.2 beta(8C30a)版本8.2(8C38)版本8.2.1(8C1002)

以上代码的PS Playground日志:

 "Constant Initialization -> Navigation" "Constant Initialization -> Navigation" "Constant Initialization -> Table" 

所以这似乎与Swift有着奇怪的“预期行为”。 它发生的原因是由于不断初始化的物业service 。 也就是说,这篇文章总结了你看得很清楚的问题: 博客文章

本质上,Obj-C底层超类泄漏内存,并且由于Obj-C初始化模式,您的service属性被初始化两次:

 - (id)init { self = [super init]; if (self) { self = [[self.class alloc] initWithNibName:nil bundle:nil]; } return self; } 

避免这种情况的简单解决方案是以下模式:

 import UIKit final class NavigationController: UINavigationController { var service: ObjectTest? convenience init() { self.init(rootViewController: UIViewController()) self.service = ObjectTest("init nav") } } class ObjectTest: NSObject{ init(_ string: String) { super.init() print(string) } } 

从您的实现中改变的只是在您的类本身初始化之后才初始化service

但是,另一种解决方案是使用指定的初始化程序为超类初始化。 这意味着您不使用将使用上述Obj-C初始化模式的便利初始化程序。