我有UINavigationController和UITableViewController的子类.
为了初始化子类,我决定使用一些方便的init方法来调用超类的一些指定的初始化器.此外,每个子类都有一些常数:
let someValue: SomeClass = SomeClass()
问题是在UINavigationController子类中,let常量被初始化为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())
我们是否允许使用如上所述的方便init?为什么?
为什么这两种情况下的方便init行为是不同的?
检查:版本8.2 beta(8C30a),版本8.2(8C38),版本8.2.1(8C1002)
附:上述代码的游乐场日志:
"Constant Initialization -> Navigation" "Constant Initialization -> Navigation" "Constant Initialization -> Table"
解决方法
所以这似乎是与Swift奇怪的“预期行为”.它发生的原因是由于不断的初始化属性服务.也就是说,这篇文章总结了你看到的问题:
blog post
本质上,Obj-C底层的超类是泄漏内存,并且由于Obj-C初始化的这种模式,您的服务属性被初始化了两次:
- (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) } }
所有这些都是从您的实现中改变的,只有在您的类本身初始化后才初始化服务.
另一种解决方案是使用指定的初始化器来进行超类的初始化.这意味着你不要使用一个方便的初始化器,它将使用上述的Obj-C初始化模式.