UINavigationController子类的便捷初始化使子类常量初始化两次 [英] Convenience initialization of UINavigationController subclass makes subclass constant init twice
问题描述
我有 UINavigationController
和 UITableViewController
的子类。
为了初始化子类,我决定使用一些调用超类的指定初始值设定项的 convenience init
方法。此外,每个子类都有一些 let
常量:
To initialize subclasses I decided to use some convenience init
methods that call some designated initializer of the superclass. Also, each subclass has some let
constant:
let someValue: SomeClass = SomeClass()
通过调用新创建的便利,可以成功初始化每个类init
方法。
Each class is successfully initialized by calling its newly created convenience init
method.
问题是 let
常量已初始化两个在 UINavigationController
子类。
The problem is that the let
constant is initialized TWICE in UINavigationController
subclass.
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
?为什么?
Are we allowed to use convenience init
like above? Why?
为什么这两种情况下便利初始
的行为有所不同?
Why is the convenience init
behavior is different in these two cases?
选中:版本8.2 beta(8C30a),版本8.2(8C38),版本8.2 .1(8C1002)
PS以上代码的游乐场日志:
P.S. Playground log of the code above:
"Constant Initialization -> Navigation"
"Constant Initialization -> Navigation"
"Constant Initialization -> Table"
推荐答案
所以这似乎与Swift有着奇怪的预期行为。它发生的原因是由于常量初始化属性 service
。也就是说,这篇文章总结了你看得很清楚的问题:博客文章
So this seems to be weirdly "expected behavior" with Swift. The reason it's happening is due to the constant initialized property service
. Namely, this post summarizes the issue your seeing pretty well: blog post
基本上,Obj-C底层超级类正在泄漏内存和你的服务
由于这种Obj-C初始化模式,属性被初始化两次:
Essentially, the Obj-C underlying super classes are leaking memory and your service
property is initialized twice because of this pattern of Obj-C initialization:
- (id)init {
self = [super init];
if (self) {
self = [[self.class alloc] initWithNibName:nil bundle:nil];
}
return self;
}
避免这种情况的简单解决方案如下:
A simple solution to avoid this is the following pattern:
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)
}
}
所有改变你的实现的是初始化服务
只有在你的类本身被初始化之后。
All that's changing from your implementation is initializing the service
only after your class itself is initialized.
另一种解决方案是使用指定的初始化程序为超类初始化。这意味着您不使用将使用上述Obj-C初始化模式的便利初始化程序。
Another solution, though, is to use the designated initializer for the superclass your initializing. Meaning that you don't use a convenience initializer which would employ the above Obj-C initialization pattern.
这篇关于UINavigationController子类的便捷初始化使子类常量初始化两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!