MLeaksFinder发现内存泄漏的弹窗项目中使用
MLeaksFinder
(原理请戳我)检测内存泄漏,十分方便和直观。会精确到某个VC,某个View。
内存泄漏大多由于循环引用,导致循环引用的几种类型:
- Block (基本项目中这种情况是最多的)
- delegate
- Timer
- Notification
Block循环引用(最常见)
- block 会被copy, 并retain block中引用的对象。为打破引用循环,用weak修饰引用的对象。
-
[weak self]
、[weak cell]
之后guard let strongSelf = self else {return}
。strongSelf
为什么不会造成引用循环。 因为strongSelf
在block中声明,相当于一个临时变量,block执行完毕后,会被释放掉,不会循环引用。 - demo
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "XXTestCell", for: indexPath) as! XXTestCell
// 防止引用循环
// 1. 重新获取一个局部cell
// cell.buttonCallBack = {
// let cell = tableView.cellForRow(at: indexPath) as? XXTestCell
// cell?.configureLabel(with: "110")
// }
// 2.不用重新获取,[weak cell]方式。以前没用过,用了之后发现很好用(推荐这种)
cell.buttonCallBack = { [weak cell] in
cell?.configureLabel(with: "110")
}
// 3. 引用循环
cell.buttonCallBack = {
cell.configureLabel(with: "110")
}
return cell
}
delegate循环引用
谨记用weak来修饰delegate一般不会有啥问题了
Timer循环引用
Notification循环引用
- 一般平常注册通知这么写,没啥问题
NotificationCenter.default.addObserver(self, selector: #selector(receivedRotation), name: UIDevice.orientationDidChangeNotification, object: nil)
@objc func receivedRotation(){
}
-
突然看到一位童鞋写了这样的代码,对,就是循环引用了。
image.png -
修改,闭包发生的内存泄漏最好解,一般用
[weak self]
,即可打破循环引用:
NotificationCenter.default.addObserver(forName: .userLoggedIn, object: nil, queue: OperationQueue.main) { [weak self] (noti) in
self?.swiftTruckSettins(self?.avoidTollsSwitch)
}
- 原因,先看此方法描述
- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
// The return value is retained by the system, and should be held onto by the caller in
// order to remove the observer with removeObserver: later, to stop observation.
文档中明确说明了,调用者会持有返回的observer对象。 VC -> observer -> block, block -> VC。具体验证详情请戳我
注:
- MLeaksFinder检测textfiled会误判泄漏,其实没有哦。
网友评论