UINavigationController子类的便捷初始化使子类常量初始化两次
我有UINavigationController
和UITableViewController
子类。
为了初始化子类,我决定使用一些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初始化模式的便利初始化程序。