我有UINavigationControllerUITableViewController的子类。

为了初始化子类,我决定使用一些convenience init方法,这些方法调用父类(super class)的某些指定的初始值设定项。而且,每个子类都有一些let常量:

let someValue: SomeClass = SomeClass()

通过调用其新创建的convenience init方法,可以成功初始化每个类。

问题是let常量在UINavigationController子类中初始化了 TWICE
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吗?为什么?

在这两种情况下,为什么convenience init行为不同?

已检查与:版本8.2 beta(8C30a),版本8.2(8C38),版本8.2.1(8C1002)

P.S.上面代码的操场日志:
"Constant Initialization -> Navigation"
"Constant Initialization -> Navigation"
"Constant Initialization -> Table"

最佳答案

因此,这似乎是Swift的“预期行为”。发生这种情况的原因是由于常量的初始化属性service。即,这篇文章总结了您所看到的问题:blog post

本质上,Obj-C基础父类(super class)正在泄漏内存,并且由于这种Obj-C初始化模式,您的service属性被初始化了两次:

- (id)init {
  self = [super init];
  if (self) {
    self = [[self.class alloc] initWithNibName:nil bundle:nil];
  }
  return self;
}

避免这种情况的简单解决方案是以下模式:
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

但是,另一种解决方案是将指定的初始化程序用于初始化的父类(super class)。意味着您不使用方便的初始化程序,而使用上面的Obj-C初始化模式。

关于ios - 方便的初始化UINavigationController子类使子类两次进行常量初始化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41262533/

10-15 19:25