咨询:13529513104

循环引用

这个是非常常见的一个问题,你可以从这里获取我们的演示    Demo

例如我们创建了一个 BadGuy() 功能只有一个,可以存一个闭包。

class BadGuy: NSObject {    var holdAction: (() -> Void)?}

然后我们从外层 ViewController 通过 Push 的方法进入 DetailViewController,DetailViewController 里创建了 10000 个 UIView 来占用些内存,badGuy 通过闭包修改了下 DetailViewController 的 hello 的属性。

import UIKitclass DetailViewController: UIViewController {var badGuy = BadGuy()var hello: String?override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view, typically from a nib.badGuy.holdAction = {self.hello = "Hello"}var a = 10000while a > 0 {a -= 1view.addSubview(UIView())}}override func didReceiveMemoryWarning() {super.didReceiveMemoryWarning()// Dispose of any resources that can be recreated.}deinit {print("Deinit")}}

在 push 前内存占用是 20M, push 后内存占用为 32.3M 反复进行几次后,内存占用会不停往上飙升,deinit 方法的打印也不会执行。

原因

holdAction 这个闭包引用了 DetailViewController 的 hello,而这个 self.hello 又因为强引用 DetailViewController 的原因,导致当你返回的时候,DetailViewController 并不会被释放。

强引用

只要有任何对象强引用对象 A,ARC 就不会摧毁 A。

弱引用

弱引用对象 B 的情况下,若没有其他物体强引用对象 B,ARC 会摧毁 B。

解药

在 GoodViewController 里我们可以通过更改强引用为弱引用的方法,来避免这种情况。

import UIKitclass GoodViewController: UIViewController {var badGuy = BadGuy()var hello: String?override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view, typically from a nib.badGuy.holdAction = { [weak self] inself?.hello = "Hello"}var a = 10000while a > 0 {a -= 1view.addSubview(UIView())}}override func didReceiveMemoryWarning() {super.didReceiveMemoryWarning()// Dispose of any resources that can be recreated.}deinit {print("Deinit")}}

做了这样的修改后,反复进行返回,进入的测试,也不会导致内存暴增了,deinit 也会在你返回的时候成功打印。

你的 App 是否有这个问题呢?


【责任编辑:(Top) 返回页面顶端