【问题标题】:How do I deinit a lazy var in Swift?如何在 Swift 中取消初始化惰性 var?
【发布时间】:2015-10-14 20:32:30
【问题描述】:

我最近一直在阅读大量关于 Swift initilization 的内容,其中一个似乎有一些优点的解决方案是利用惰性变量来避免可选选项的厄运和阴暗,尤其是在扩展 UIViewControllers 或沿这些线的其他类时.考虑到这一点,我的代码如下所示:

final class MyViewController : UIViewController {
    lazy private var myOtherViewController: MyOtherViewController = MyOtherViewController()

    deinit {
        // myOtherViewController = nil // Can't do this. Expression resolves to an unused l-value
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        myOtherViewController.foo();
    }
}

// elsewhere...
final class MyOtherViewController : UIViewController {
    deinit {
        print("Deinit!")
    }
}

在此处的示例中似乎MyOtherViewControllerdeinit 方法似乎永远不会触发,但我也无法使myOtherViewController deinit。不允许将其设置为 nil。有什么我想念的东西迫使MyOtherViewController 保留吗?还是我只是对垃圾收集器不耐烦了?

【问题讨论】:

  • 为什么需要deinit?大多数情况下,根据文档,你没有,我不明白你为什么这样做......developer.apple.com/library/ios/documentation/Swift/Conceptual/…
  • 这是一个架构问题,比什么都重要。我的目标是仅在需要时创建对象,并且在不再需要时仍然可以控制将其删除,例如内存警告。可选的似乎是要走的路。
  • 顺便说一句,保持对另一个视图控制器的强引用有点令人不安。同样,我建议不要以与将此控制器添加到视图控制器层次结构的方式(例如,包含调用、呈现等)断开连接的方式实例化视图控制器。如果你需要自己引用这个其他视图控制器,你通常会有一个弱引用,并让视图控制器层次结构来处理所有权。

标签: ios swift swift2


【解决方案1】:

为此,您的惰性变量必须声明为可选,即使您打算在需要值时立即初始化它(即惰性)。

class MyObject {

    func run() {
        print( "MyObject :: run()" )
    }

    init() {
        print( "MyObject :: init" )
    }

    deinit {
        print( "MyObject :: deinit" )
    }
}

class MyContext {
    lazy var myObject:MyObject? = MyObject()
}

let myContext = MyContext()
myContext.myObject?.run()   //< "MyObject :: init"
myContext.myObject = nil    //< "MyObject :: deinit"

另外,我不同意“可选项的厄运和悲观”的概念——人们只需要知道在许多可用技术中哪一种是最方便和实用的方法来处理它们,以及如何避免允许过多的状态排列存在于给定上下文中可选值和非可选值的组合中。此外,一个可选项实际上正是您想要的,因为您打算 取消它。使用一个可选项并不意味着在你初始化它之前,一个值现在将是nil,而是它可能在其生命周期的任何时候都是nil,即使它是在声明时或任何其他时间预先定义的.如果避免选项对您来说真的是那么高的优先级,那么您将不得不退后一步并重新评估您的架构,以创造一种不再需要取消初始化值的情况。

【讨论】:

    【解决方案2】:

    我同意 Grimxn 的观点,这种将属性设置为 nil 的模式(因此需要将其设为可选才能做到这一点)是不必要的。当MyViewController 被释放时,它会自动释放对MyOtherViewController 的强引用。

    你需要手动nil这个属性的唯一时候是当你必须解决一个强引用循环时(如果你有这样的循环,你不能在deinit中解决它,而是viewDidDisappear或类似的东西)。

    如果您没有看到这个其他视图控制器被释放,那么我建议您找到强引用循环的来源并解决它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      • 1970-01-01
      相关资源
      最近更新 更多