我有以下功能:
func attachToComment(_ data: Data, url: URL?, type: MediaType) {
self.dismiss(animated: true, completion: nil)
let image = UIImage(data: data)!
model.attachmentData = data
model.attachmentVideoURL = url
model.attachmentType = type
toolbar.attachImage(image, withType: type)
}
这传递给对视图控制器的引用,该引用以模态显示:
containerNavViewController.attachToComment = attachToComment
ContainerNavViewController
是一个UINavigationController
,其中具有容器视图控制器。这将显示相机,并在拍摄图像后将attachToComment
函数传递给下一个视图控制器EditImageViewController
。在ContainerNavViewController内部,我有以下代码:var attachToComment: ((_ data: Data, _ url: URL?, _ type: MediaType) -> ())?
var model = CameraModel()
....
editImageViewController.attachToComment = self.attachToComment
editImageViewController.model = model
self.navigationController?.pushViewController(editImageViewController, animated: false)
在EditImageViewController内部,我有以下代码调用了闭包:
attachToComment(model.imageData, model.videoURL, model.mediaType)
然后,这将调用原始函数并关闭模式视图控制器。但是,在这些视图上未调用deinit,它们在后台非常“活跃”。我的内存泄漏在哪里,如何预防?
最佳答案
正如Dare和Sealos都暗示的那样,该问题可能是一个强大的参考周期。但是,仅在问题中提供的代码不足以导致这样的循环(因为当您关闭editImageViewController
时,如果不再有对其的强引用,则释放闭包并破坏强引用循环)。
但是,一些观察结果:
但是,如果提供
editImageViewController
的视图控制器对它的引用保持强烈,从而阻止了它的发布,那么我可以引发一个强大的引用周期。 editImageViewController
是局部变量,还是属性?如果是属性,请将其更改为局部变量,这样可以解决问题。或者,也许其他一些东西对editImageViewController
保持了强烈引用(例如,重复计时器或类似的东西)。您可以使用“调试内存图”工具(请参见下面的第3点)来确定哪些是
editImageViewController
的强引用。 attachToComment
的EditImageViewController
对当前呈现的视图控制器没有严格的引用,我将替换为:editImageViewController.attachToComment = attachToComment
与:
editImageViewController.attachToComment = { [weak self] data, url, type in
self?.attachToComment(data, url: url, type: type)
}
这是确保
attachToComment
中的editImageViewController
闭包不维护对呈现视图控制器的强引用的最简单方法。 EditImageViewController
的所有权。例如,我举了两个例子:editImageViewController
存储为呈现视图控制器的属性,而不是将其保留为局部变量(第1点);和weak
模式(第2点)。 当我这样做时,我得到了这样的内存图:
从该图中,我不必猜测问题的根源是什么。我不仅可以看到存在强大的参考周期,而且可以看到引起问题的具体原因。但是,如果我修复以上两个问题中的一个(或两个),则此周期消失。
关于ios - 通过闭包导致内存泄漏,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40408476/