我有UINavigationController
和UITableViewController
的子类。
为了初始化子类,我决定使用一些convenience init
方法,这些方法调用父类(super class)的某些指定的初始值设定项。而且,每个子类都有一些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"
最佳答案
因此,这似乎是Swift的“预期行为”。发生这种情况的原因是由于常量的初始化属性service
。即,这篇文章总结了您所看到的问题:blog post
本质上,Obj-C基础父类(super class)正在泄漏内存,并且由于这种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
。但是,另一种解决方案是将指定的初始化程序用于初始化的父类(super class)。意味着您不使用方便的初始化程序,而使用上面的Obj-C初始化模式。
关于ios - 方便的初始化UINavigationController子类使子类两次进行常量初始化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41262533/