【发布时间】:2019-08-11 08:45:08
【问题描述】:
据我所知,在不应该发生泄漏的情况下,我遇到了无主自我的泄漏。让我举个例子,有点做作,所以请耐心等待,我已经尽量做到了最简单的情况。
假设我有一个简单的视图控制器,它在 viewDidLoad 上执行一个闭包:
class ViewController2: UIViewController {
var onDidLoad: (() -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
onDidLoad?()
}
}
还有一个类,ViewHandler,它拥有这个视图控制器的一个实例,并使用一个无主的引用将一个通知函数的调用注入到它的闭包中:
class ViewHandler {
private let viewController2 = ViewController2()
func getViewController() -> ViewController2 {
viewController2.onDidLoad = { [unowned self] in
self.notify()
}
return viewController2
}
func notify() {
print("My viewcontroller has loaded its view!")
}
}
然后,当它的视图控制器被另一个视图控制器呈现时,ViewHandler 在被取消时泄漏:
class ViewController: UIViewController {
private var viewHandler: ViewHandler?
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
viewHandler = ViewHandler()
self.present(viewHandler!.getViewController(), animated: true, completion: nil)
viewHandler = nil // ViewHandler is leaking here.
}
}
我知道这个例子可能看起来有点做作,但据我所知不应该有泄漏。让我尝试分解它:
在呈现 ViewHandler.ViewController2 之前,所有权应如下所示:
ViewController -> ViewHandler -> ViewController2 -|
^ |
|_ _ _ _ unowned _ _ _ _ _ |
呈现 ViewHandler.ViewController2 后,所有权应如下所示:
_______________________________
| v
ViewController -> ViewHandler -> ViewController2 -|
^ |
|_ _ _ _ unowned _ _ _ _ _ |
取消 ViewHandler 后,所有权应如下所示:
_______________________________
| v
ViewController ViewHandler -> ViewController2 -|
^ |
|_ _ _ _ unowned _ _ _ _ _ |
没有任何东西拥有 ViewHandler,它应该被释放。然而事实并非如此,ViewHandler 正在泄漏。
如果我将注入到 onDidLoad 的闭包的捕获列表中的引用更改为弱,则不会泄漏,并且 ViewHandler 会按预期释放:
func getViewController() -> ViewController2 {
viewController2.onDidLoad = { [weak self] in
self?.notify()
}
return viewController2
}
另外,有些我无法解释,如果我保持引用为无主并让 ViewHandler 从 NSObject 继承,ViewHandler 会按预期释放并且没有泄漏:
class ViewHandler: NSObject {
private let viewController2 = ViewController2()
func getViewController() -> ViewController2 {
viewController2.onDidLoad = { [unowned self] in
self.notify()
}
return viewController2
}
....
}
谁能解释一下是怎么回事?
【问题讨论】:
标签: swift memory-leaks presentmodalviewcontroller ownership-semantics unowned-references