iOS 常見內(nèi)存泄漏

一、基本概念

  1. 內(nèi)存泄漏(memory leak):是指申請(qǐng)的內(nèi)存空間使用完畢之后未回收。
    一次內(nèi)存泄露危害可以忽略,但若一直泄漏,無(wú)論有多少內(nèi)存,遲早都會(huì)被占用光,最終導(dǎo)致程序crash。(因此,開發(fā)中我們要盡量避免內(nèi)存泄漏的出現(xiàn))
  2. 內(nèi)存溢出(out of memory):是指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用。
    通俗理解就是內(nèi)存不夠用了,通常在運(yùn)行大型應(yīng)用或游戲時(shí),應(yīng)用或游戲所需要的內(nèi)存遠(yuǎn)遠(yuǎn)超出了你主機(jī)內(nèi)安裝的內(nèi)存所承受大小,就叫內(nèi)存溢出。最終導(dǎo)致機(jī)器重啟或者程序crash。

二、常見內(nèi)存泄露

1、NSTimer循環(huán)引用

[NSTimer scheduledTimerWithTimeInterval:1.0 
                                 target:self 
                               selector:@selector(updateTime:) 
                               userInfo:nil 
                                repeats:YES];

  • 理由: 這時(shí) target: self,增加了ViewController的retain count,
    即self強(qiáng)引用timer,timer強(qiáng)引用self,造成循環(huán)引用。

2、ViewController中的代理delegate

  • 理由:如果代理用strong修飾,ViewController(self)會(huì)強(qiáng)引用View,View強(qiáng)引用delegate,delegate內(nèi)部強(qiáng)引用ViewController(self)。造成內(nèi)存泄漏。
  • 解決方案:代理盡量使用weak修飾。
@class QiAnimationButton;
@protocol QiAnimationButtonDelegate <NSObject>

- (void)animationButton:(QiAnimationButton *)button willStartAnimationWithCircleView:(QiCircleAnimationView *)circleView;
@end

@interface QiAnimationButton : UIButton

@property (nonatomic, weak) id <QiAnimationButtonDelegate> delegate;

3、Block

  • 理由:如果block被當(dāng)前ViewController(self)持有,這時(shí),如果block內(nèi)部再持有ViewController(self),就會(huì)造成循環(huán)引用。
  • 解決方案:在block外部對(duì)弱化self,再在block內(nèi)部強(qiáng)化已經(jīng)弱化的weakSelf
__weak typeof(self) weakSelf = self;
    [self.operationQueue addOperationWithBlock:^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        }
    }];

4、WKWebView 造成的內(nèi)存泄漏

  • 理由: 但是其實(shí) “addScriptMessageHandler” 這個(gè)操作,導(dǎo)致了 wkWebView 對(duì) self 進(jìn)行了強(qiáng)引用,然后 “addSubview”這個(gè)操作,也讓 self 對(duì) wkWebView 進(jìn)行了強(qiáng)引用,這就造成了循環(huán)引用。
  • 解決方案: 解決方法就是在合適的機(jī)會(huì)里對(duì) “MessageHandler” 進(jìn)行移除操作。
- (void)viewDidDisappear:(BOOL)animated {
         [super viewDidDisappear:animated];
          [_wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"WKWebViewHandler"];
}

5、NSNotification

@property (nonatomic, strong) id observer; //持有注冊(cè)通知后返回的對(duì)象

__weak __typeof__(self) weakSelf = self;
 _observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"
                                                               object:nil
                                                                queue:nil
                                                           usingBlock:^(NSNotification *note) {
     __typeof__(self) strongSelf = weakSelf;
     [strongSelf dismissModalViewControllerAnimated:YES];
 }];

6、加載大圖片或者多個(gè)圖片
[UIImage imageNamed:@""],次方法使用了系統(tǒng)緩存來(lái)緩存圖像,會(huì)長(zhǎng)時(shí)間占用內(nèi)存,最好使用imageWithContentsOfFile方法;

7、ANF的AFHTTPSessionManager

  • 在封裝網(wǎng)絡(luò)請(qǐng)求類時(shí)需注意的是需要將請(qǐng)求隊(duì)列管理者AFHTTPSessionManager聲明為單例創(chuàng)建形式。進(jìn)行全局管理,防止內(nèi)存泄漏

8、地圖類

  • 理由: 若項(xiàng)目中使用地圖相關(guān)類,一定要檢測(cè)內(nèi)存情況,因?yàn)榈貓D是比較耗費(fèi)App內(nèi)存的。
  • 解決方案: 因此在根據(jù)文檔實(shí)現(xiàn)某地圖相關(guān)功能的同時(shí),我們需要注意內(nèi)存的正確釋放,大體需要注意的有需在使用完畢時(shí)將地圖、代理等滯空為nil,注意地圖中標(biāo)注(大頭針)的復(fù)用,并且在使用完畢時(shí)清空標(biāo)注數(shù)組等。

9、MKMapView

三、iOS內(nèi)存泄露檢測(cè)

iOS內(nèi)存泄露檢測(cè)

參考文檔

iOS 內(nèi)存泄漏排查方法及原因分析
iOS 內(nèi)存泄漏的幾種原因
iOS內(nèi)存相關(guān)的知識(shí)點(diǎn)整理
iOS之NSTimer循環(huán)引用的解決方案
iOS內(nèi)存泄露檢測(cè)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容