因近期項(xiàng)目需要開發(fā)布會描孟,所以花了幾天時(shí)間排查了項(xiàng)目里面的問題益兄。發(fā)現(xiàn)了項(xiàng)目中存在著比較嚴(yán)重的內(nèi)存泄漏的問題戒洼。也借著這樣的機(jī)會查看了一下iOS內(nèi)存泄漏的原因以及排查方式燕垃。
排查方式
Xcode提供了內(nèi)置的Instruments工具枢劝,幫助我們?nèi)ヅ挪閮?nèi)存泄漏的問題,但是說實(shí)話卜壕,自帶的排查工具排查起來真的是比較費(fèi)時(shí)您旁。因此,我在查詢一些iOS內(nèi)存泄漏監(jiān)測自動(dòng)化的文章時(shí)候發(fā)現(xiàn)了一些比較好用的工具轴捎,一個(gè)是Facebook開源的三劍客(FBRetainCycleDetector,FBAllocationTracker,FBMemoryProfiler)鹤盒,另外的則是微信閱讀團(tuán)隊(duì)的MLeaksFinder蚕脏。
關(guān)于 MLeaksFinder 這里有兩篇其官方提供的文章介紹:
簡單來說,MLeaksFinder 是從 UIViewController 入手侦锯。當(dāng)一個(gè)UIViewController 被 pop 或 dismiss 后驼鞭,該 UIViewController 包括它的 view,view 的 subviews 等等將很快被釋放(除非你把它設(shè)計(jì)成單例尺碰,或者持有它的強(qiáng)引用挣棕,但一般很少這樣做)。只需在一個(gè) ViewController 被 pop 或 dismiss 一小段時(shí)間后亲桥,看看該 UIViewController洛心,它的 view,view 的 subviews 等等是否還存在题篷。
MLeaksFinder 的原理非常簡單而且有效皂甘,幫助我排查了 App 中存在的不少內(nèi)存泄漏問題,而且對于整個(gè)應(yīng)用基本零侵入悼凑,不需要做任何的配置與修改偿枕。使用方法也異常簡單(pod 'MLeaksFinder'
),無需添加任何代碼,也無需導(dǎo)入任何頭文件户辫。
Xcode內(nèi)置的工具排查
1.靜態(tài)內(nèi)存分析
靜態(tài)分析的方法能夠發(fā)現(xiàn)大部分的問題渐夸,但是使用靜態(tài)分析,并不能完全的排查到所有的內(nèi)存泄漏問題渔欢,因此我們需要使用Leaks進(jìn)行動(dòng)態(tài)內(nèi)存分析墓塌。
2.動(dòng)態(tài)內(nèi)存分析
當(dāng)我們打開Instruments之后,我們可以看到項(xiàng)目已經(jīng)自動(dòng)啟動(dòng)了奥额,因?yàn)長eaks是動(dòng)態(tài)監(jiān)測苫幢,所以當(dāng)我們進(jìn)行操作的時(shí)候,可以檢測項(xiàng)目其他界面是否存在著內(nèi)存泄漏垫挨。
iOS內(nèi)存泄漏原因分析
- block的循環(huán)引用
- delegate循環(huán)引用問題
- 定時(shí)器(NSTimer)的不合理的使用
- 加載大量圖片導(dǎo)致內(nèi)存暴漲
Block的使用
使用block的時(shí)候韩肝,可能經(jīng)常會碰到的一個(gè)問題就是block體內(nèi)使用了self.xx,從而相互強(qiáng)指向九榔,造成了循環(huán)引用哀峻。
解決方法:
//MRC下代碼如下
__block Viewcontroller *weakSelf = self;
//ARC下代碼如下
__weak Viewcontroller *weakSelf = self;
當(dāng)然現(xiàn)在一般的項(xiàng)目,基本上都是使用的ARC來管理內(nèi)存的哲泊。當(dāng)然剩蟀,并不是所有的block都會造成循環(huán)引用,例如使用系統(tǒng)自帶的UIView 的Blcok切威,就不會產(chǎn)生循環(huán)引用育特,這里就不做深層次的探究了。
delegate的使用
使用strong
進(jìn)行修飾的時(shí)候先朦,對象會強(qiáng)引用delegate缰冤,外界無法銷毀delegate對象犬缨,會導(dǎo)致循環(huán)引用,這時(shí)候我們就可以使用weak
進(jìn)行修飾锋谐,weak
修飾的對象在釋放后遍尺,指針地址會被置為nil,是一種弱引用涮拗。
定時(shí)器(NSTimer)的使用
不使用 NSTimer的時(shí)候注意要銷毀NSTimer對象乾戏。
[timer invalidate];
timer = nil;
加載大量圖片
1.加載重復(fù)的圖片,最好使用`imageNamed`的方式加載三热。
2.當(dāng)你不需要重用該圖像鼓择,或者你需要將圖像以數(shù)據(jù)方式存儲到數(shù)據(jù)庫,又或者你要通過網(wǎng)絡(luò)下載一個(gè)很大的圖像時(shí)就漾,請盡量使用`imageWithData`的方式加載圖像呐能。