首先我们先写一段有问题的代码,然后运行一次使App安装在手机或模拟器上,然后Xcode=>Open Developer Tool=>Instruments打开Instruments面板,选择Leaks。
import UIKit
class Person{
var assets=[Asset]()
func takeAsset(asset:Asset){
asset.owner=self
assets.append(asset)
}
}
class Asset{
var owner:Person?
}
class MainViewController: UIViewController {
@IBOutlet weak var testButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
//申请了内存但是不释放
let _=UnsafeMutablePointer<Int>.allocate(capacity: 100)
}
@IBAction func testButtonDidClick(_ sender: Any) {
//循环强引用
let person=Person()
let asset=Asset()
person.takeAsset(asset: asset)
}
}
点击左上角的红色圆点即可开始内存泄露检测,Leak Checks上方的All Heap & Anonymous VM是内存分配情况,当Leak Checks出现红色叉叉时说明有内存泄露,鼠标点击Leak Checks可以看到内存泄露信息。
Leaks by Backtrace可以看到泄露的对象,地址,大小以及栈回溯,Cycles & Roots可以更直观地看到内存泄露和循环引用情况,Call Tree里显示的是泄露内存分配时的栈回溯,上述三处都有栈回溯,但并不是每次都有。
看不到栈回溯不好定位出问题的代码,我们可以记录泄露的内存地址,然后在Allocations List中找到该地址查看栈回溯,如果栈回溯里显示的是代码地址而不是函数名,这通常是找不到符号名称导致的,可以尝试在Build Settings中设置Debug Infomation Format为DWARF with dSYM File。
另外Call Tree有几个选项可以方便我们查看栈回溯:
- Separate by Thread:将栈回溯按照线程分离
- Invert Call Tree:将栈回溯顺序颠倒
- Hide System Libraries:隐藏系统栈回溯
- Flatten Recursion:将递归调用合并成一个
网友评论