UINavigationController子类的便捷初始化使子类常量初始化两次 [英] Convenience initialization of UINavigationController subclass makes subclass constant init twice

查看:110
本文介绍了UINavigationController子类的便捷初始化使子类常量初始化两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆