我有 UINavigationController
和 UITableViewController
的子类.
I have subclasses of UINavigationController
and 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()
通过调用其新创建的convenience init
方法成功初始化每个类.
Each class is successfully initialized by calling its newly created convenience init
method.
问题是 let
常量在 UINavigationController
子类中被初始化TWICE.
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?
为什么这两种情况下的convenience init
行为不同?
Why is the convenience init
behavior is different in these two cases?
检查:版本 8.2 beta (8C30a)、版本 8.2 (8C38)、版本 8.2.1 (8C1002)
附:上面代码的 Playground 日志:
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 底层超类正在泄漏内存,并且您的 service
属性被初始化两次,因为这种 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)
}
}
你的实现所改变的只是在你的类本身被初始化之后才初始化service
.
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 子类的便捷初始化使得子类常量初始化两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!