转载

iOS App 的内存释放问题

循环引用

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

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

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

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

import UIKit class 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 = 10000   while a > 0 {    a -= 1    view.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 UIKit class 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] in    self?.hello = "Hello"   }   var a = 10000   while a > 0 {    a -= 1    view.addSubview(UIView())   }  }  override func didReceiveMemoryWarning() {   super.didReceiveMemoryWarning()   // Dispose of any resources that can be recreated.  }  deinit {   print("Deinit")  } }  

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

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

正文到此结束
Loading...