[TOC]
Xcode8使用Memory Graph
-
第一步:真机下运行APP后,点击
image.png -
第二步:查看issue面板,注意选择右边Runtime
image.png -
第三步:查看可能出现的内存泄露
image.png
比如上图的1 instance of __NSMallocBlock_leaked
,点击后出现下图
原因在于如下代码
group.didSelectedRowBlock = { [unowned self, group] row in
guard let indexPaths = group.selectedIndexPaths else {return}
if indexPaths.count > 0 {
self.shouldAdd = true
let row = (indexPaths.firstObject as! IndexPath).row
self.deviceAttri?.attrValue = String(row)
} else {
self.shouldAdd = false
}
}
group的block中又使用了group,导致了循环引用,虽然使用了[unowned group],事实证明并没有效果
最后的解决办法是修改didSelectedRowBlock的接口,直接将selectedIndexPaths参数传入block参数中:
group.didSelectedRowBlock = { [unowned self] indexPaths in
guard let indexPaths = indexPaths else {return}
if indexPaths.count > 0 {
self.shouldAdd = true
self.deviceAttri?.attrValue = String(indexPaths.first!.row)
} else {
self.shouldAdd = false
}
}
-
第四步:在 debug 页面查看内存泄露情况
image.png
有叹号说明需要注意可能存在内存泄露,可以看到 CoreFoundation中也可能存在内存泄露情况
使用Instruments的Leaks工具
Time Profiler
- 查看多个线程里那些方法费时过多的方法
-
Call Tree上会默认按照费时的线程进行排序,单个线程中会也会按照对应的费时方法排序
image.png
Allocations
- 可以对每个动作的前后进行Generations,对比内存的增加,查看使内存增加的具体的方法和代码所在位置
- 具体操作
- 在右侧Generation Analysis里点击Mark Generation,这样会产生一个Generation,
- 切换到其他页面或一段时间产生了另外一个事件时再点Mark Generation来产生一个新的Generation,
- 这样反复,生成多个Generation,查看这几个Generation会看到Growth的大小,如果太大可以点进去查看相应占用较大的线程里右侧Heaviest Stack Trace里查看对应的代码块,然后进行相应的处理。
Leak
可以在上面区域的Leaks部分看到对应的时间点产生的溢出,选择后在下面区域的Statistics>Allocation Summary
能够看到泄漏的对象,同样可以通过Stack Trace查看到具体对应的代码区域。
网友评论