ios – UINavigationController子类的方便初始化使子类常量初始化两次

前端之家收集整理的这篇文章主要介绍了ios – UINavigationController子类的方便初始化使子类常量初始化两次前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有UINavigationController和UITableViewController的子类.

为了初始化子类,我决定使用一些方便的init方法调用超类的一些指定的初始化器.此外,每个子类都有一些常数:

let someValue: SomeClass = SomeClass()

每个类都通过调用其新创建的方便init方法来成功初始化.

问题是在UINavigationController子类中,let常量被初始化为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())

我们是否允许使用如上所述的方便init?为什么?

为什么这两种情况下的方便init行为是不同的?

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

附:上述代码的游乐场日志:

"Constant Initialization -> Navigation"
"Constant Initialization -> Navigation"
"Constant Initialization -> Table"

解决方法

所以这似乎是与Swift奇怪的“预期行为”.它发生的原因是由于不断的初始化属性服务.也就是说,这篇文章总结了你看到的问题: blog post

本质上,Obj-C底层的超类是泄漏内存,并且由于Obj-C初始化的这种模式,您的服务属性被初始化了两次:

- (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)
    }
}

所有这些都是从您的实现中改变的,只有在您的类本身初始化后才初始化服务.

另一种解决方案是使用指定的初始化器来进行超类的初始化.这意味着你不要使用一个方便的初始化器,它将使用上述的Obj-C初始化模式.

猜你在找的iOS相关文章