遇到一个内存暴增的issue,各种分析啊,静态动态tools全上了,然并卵。
后来只能用笨办法了,找到最有可能的那几个类,先在deinit方法里面写个debugprint,然后跑app,看日志,不写内容直接断点方法在swift中是不会停的 -,-
运气不错发现了有一个vc不会走该方法,自然该vc中持有的相关的类也不会被释放,导致每次加载此vc都会重新分配新的内存,点多了之后,7p上点了30多次,我的i8点了140多次吧,会出现内存不足闪退或者界面异常,不得不服测试同学的毅力。。。
接着针对这个vc进行分析,因为instruments里面并不能显示出来这个内存问题,,所以只能在viewDidLoad里面对每一个操作进行注释或打开进行反复操作。最后发现是有一行通知注册的代码会影响deinit方法的调用,但我明显已经移除了观察者呢。
不过这里用的方法确实不是我平时用的那个API,我用的是addObserver(forName,平时用的是addObserver(_ observer: Any, :selector, 具体点说我用了那个传参里面没有观察者的方法,并且有返回一个nsobjectprotocol对象,常用的那个是需要传入观察者的,并没有返回值的。这也是想满足代码结构才会想用这个新的api,有一个闭包返回,直接接受通知回调,但没有去细看居然有一个返回值。
以下是官方的使用范例:
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
self.localeChangeObserver = center.addObserverForName(NSCurrentLocaleDidChangeNotification, object: nil, queue: mainQueue) { (note) in
print("The user's locale changed to: \(NSLocale.currentLocale().localeIdentifier)")
}
let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
var token: NSObjectProtocol?
token = center.addObserverForName("OneTimeNotification", object: nil, queue: mainQueue) { (note) in
print("Received the notification!")
center.removeObserver(token!)
}
另外就是一个新的发现(不新了),一直没有关注到,文档里面的一句话
If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its `dealloc` method. Otherwise, you should call removeObserver(_:name:object:) before `observer` or any object passed to this method is deallocated.
原来使用我常用的那个方法,在9.0或之后就不需要去移除观察者了。
当然,这个新方法还是要移除的,人家都写了。
To unregister observations, you pass the object returned by this method to removeObserver(_:). You must invoke removeObserver(_:) or removeObserver(_:name:object:) before any object specified by addObserver(forName:object:queue:using:) is deallocated.
之前使用基本方法都是按习惯来,毕竟干了这么多年的iOS了,那些常用的方法基本都能背下来,大意,导致的这次bug,作为一个码农,还是要继续努力,保持初心。