我有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)
P.S。以上代码的游乐场日志:
"Constant Initialization -> Navigation"
"Constant Initialization -> Navigation"
"Constant Initialization -> Table"
答案 0 :(得分:4)
所以这似乎与Swift一样奇怪的“预期行为”。它发生的原因是由于常量初始化属性service
。也就是说,这篇文章总结了您看得很清楚的问题:blog post
基本上,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初始化模式的便利初始化程序。