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

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

问题描述

我有 UINavigationControllerUITableViewController 的子类.

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 子类的便捷初始化使得子类常量初始化两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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