我最近一直在阅读关于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!")
}
}
在此示例中显示 MyOtherViewController
的{{1}}方法似乎永远不会触发,但我也无法让deinit
删除。不允许将其设置为myOtherViewController
。是否有一些我错过的强迫nil
保留的东西?或者我对垃圾收集器感到不耐烦?
答案 0 :(得分:4)
要做到这一点,你的懒惰变量必须被声明为可选,即使你想要在需要值时(即懒惰地)初始化它。
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
,即使它是在声明或任何其他时间事先。如果避免选项对您来说确实具有高优先级,那么您必须退后一步并重新评估您的体系结构,以创建一种不再需要对值进行去初始化的情况。
答案 1 :(得分:2)
我同意Grimxn的观点,这种将该属性设置为nil
的模式(因此需要使其成为可选项以便能够这样做)是不必要的。取消分配MyViewController
后,它会自动释放其对MyOtherViewController
的强引用。
您需要手动nil
此属性的唯一时间是您必须解决强引用周期(如果您有这样的周期,则无法在deinit
中解决此问题,而是viewDidDisappear
或类似的事情。)
如果您没有看到其他视图控制器被取消分配,那么我建议找到强引用周期的来源并解决它。