iWh*_*Buy 15 uinavigationcontroller ios swift
我有UINavigationController和的子类UITableViewController.
为了初始化子类,我决定使用一些convenience init调用超类的指定初始化器的方法.此外,每个子类都有一些let常量:
let someValue: SomeClass = SomeClass()
Run Code Online (Sandbox Code Playgroud)
通过调用其新创建的convenience init方法成功初始化每个类.
问题是let常量在子类中初始化为TWICEUINavigationController.
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())
Run Code Online (Sandbox Code Playgroud)
我们可以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"
Run Code Online (Sandbox Code Playgroud)
所以这对于 Swift 来说似乎是奇怪的“预期行为”。发生这种情况的原因是由于常量初始化属性service。也就是说,这篇文章很好地总结了您所看到的问题:博客文章
本质上,Obj-C 底层超类正在泄漏内存,并且service由于 Obj-C 初始化的这种模式,您的属性被初始化两次:
- (id)init {
self = [super init];
if (self) {
self = [[self.class alloc] initWithNibName:nil bundle:nil];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
避免这种情况的一个简单解决方案是以下模式:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
您的实现所发生的所有变化只是service在您的类本身初始化之后才进行初始化。
不过,另一种解决方案是对要初始化的超类使用指定的初始化程序。这意味着您不使用使用上述 Obj-C 初始化模式的便利初始化程序。