ios的幾種內(nèi)存泄漏

一谆趾、從AFNet說起

對(duì)于iOS開發(fā)者躁愿,網(wǎng)絡(luò)請(qǐng)求類AFNetWorking是再熟悉不過了,對(duì)于AFNetWorking的使用我們通常會(huì)對(duì)通用參數(shù)沪蓬、網(wǎng)址環(huán)境切換彤钟、網(wǎng)絡(luò)狀態(tài)監(jiān)測(cè)、請(qǐng)求錯(cuò)誤信息等進(jìn)行封裝跷叉。在封裝網(wǎng)絡(luò)請(qǐng)求類時(shí)需注意的是需要將請(qǐng)求隊(duì)列管理者AFHTTPSessionManager聲明為單例創(chuàng)建形式逸雹。對(duì)于該問題,AFNetWorking的作者在gitHub上也指出建議使用者在相同配置下保證AFHTTPSessionManager只有一個(gè)云挟,進(jìn)行全局管理梆砸,因此我們可以通過單例形式進(jìn)行解決。下方展示部分核心代碼:

+?(AFHTTPSessionManager*)defaultNetManager?{

????static?AFHTTPSessionManager?*manager;

????static?dispatch_once_t?onceToken;

????dispatch_once(&onceToken,?^{

????????manager?=?[[AFHTTPSessionManager?alloc]init];

????????manager.responseSerializer?=?[AFHTTPResponseSerializer?serializer];

????});

????returnmanager;

}

+?(void)GET:(NSString*)url?parameters:(NSDictionary*)parameter?returnData:(void?(^)(NSData?*?resultData,NSError?*?error))returnBlock{

????//請(qǐng)求隊(duì)列管理者?單例創(chuàng)建形式?防止內(nèi)存泄漏

????AFHTTPSessionManager?*?manager?=?[HttpRequest?defaultNetManager];

????[manager?GET:url?parameters:parameter?progress:^(NSProgress?*?_Nonnull?downloadProgress)?{

????}?success:^(NSURLSessionDataTask?*?_Nonnull?task,?id??_Nullable?responseObject)?{

????????returnBlock(responseObject,nil);

????}?failure:^(NSURLSessionDataTask?*?_Nullable?task,?NSError?*?_Nonnull?error)?{

????????returnBlock(nil,error);

????}];

}

二园欣、Block循環(huán)引用

Block循環(huán)引用的問題已是老經(jīng)常談了帖世,至今已有多篇文章詳細(xì)解釋其原理及造成循環(huán)引用的原因等,不泛畫圖或?qū)嵗信e沸枯,這里不一一贅述日矫÷腹總結(jié)一句話防止Block循環(huán)引用就是要防止對(duì)象之間引用的閉環(huán)出現(xiàn)。舉個(gè)開發(fā)中的實(shí)際例子哪轿,就拿很多人在用的MJRefresh說self.tableView.mj_header?=?[MJRefreshNormalHeader?headerWithRefreshingBlock:^{

????????self.page?=?1;

????????[self.dataArr?removeAllObjects];

????????[self?loadData];

}];

若在MJRefresh的執(zhí)行Block中調(diào)用當(dāng)前self或其所屬屬性盈魁,一定要注意循環(huán)引用問題。我們簡(jiǎn)單分析下MJRefresh為什么會(huì)造成循環(huán)引用問題:

點(diǎn)擊進(jìn)入headerWithRefreshingBlock對(duì)應(yīng)方法即可

#pragma?mark?-?構(gòu)造方法

+?(instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock

{

????MJRefreshHeader?*cmp?=?[[self?alloc]?init];

????cmp.refreshingBlock?=?refreshingBlock;

????returncmp;

}

這里僅有三行代碼窃诉,無非就是創(chuàng)建了下拉刷新部分View然后返回杨耙,這里比較重要的是cmp.refreshingBlock = refreshingBlock;這一句,這里的refreshingBlock是屬于MJRefreshHeader的強(qiáng)引用屬性褐奴,最后header會(huì)成為我們自己tableView的強(qiáng)引用屬性mj_header按脚,也就是說self.tableView強(qiáng)引用header, header強(qiáng)引用refreshingBlock,如果refreshingBlock里面強(qiáng)引用self敦冬,就成了循環(huán)引用辅搬,所以必須使用weakSelf,破掉這個(gè)循環(huán)脖旱。畫圖表示為:

循環(huán)引用示意圖

閉環(huán)為:

self--->self.tableView--->self.tableView.mj_header---

>self.tableView.mj_header.refreshingBlock--->self

解決方案大家應(yīng)該也不陌生

__weak?typeof(self)?weakself?=?self;?

self.tableView.mj_header?=?[MJRefreshNormalHeader?headerWithRefreshingBlock:^{

????????__strong?typeof(self)?strongself?=?weakself;

????????strongself.page?=?1;

????????[strongself.dataArr?removeAllObjects];

????????[strongself?loadData];

}];

【??strongself是為了防止內(nèi)存提前釋放堪遂,有興趣的童鞋可深入了解,這里不做過多解釋了萌庆。當(dāng)然也可借助libextobjc庫(kù)進(jìn)行解決溶褪,書寫為@weakify和@strongify會(huì)更方便些〖眨】

相應(yīng)的對(duì)于自定義View中的一些Block傳值問題同樣需要注意猿妈,與上述類似。

三巍虫、delegate循環(huán)引用問題

delegate循環(huán)引用問題比較基礎(chǔ)彭则,只需注意將代理屬性修飾為weak即可

1@property?(nonatomic,?weak)?id?delegate;

下圖比較形象的說明了使用weak修飾就是為了防止ViewController和UITableView相互強(qiáng)引用內(nèi)存無法釋放的問題:

delegate循環(huán)引用

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

對(duì)于定時(shí)器NSTimer占遥,使用不正確也會(huì)造成內(nèi)存泄漏問題俯抖。這里簡(jiǎn)單舉個(gè)例子,我們聲明了一個(gè)類TestNSTimer瓦胎,在其init方法中創(chuàng)建定時(shí)器執(zhí)行操作芬萍。

#import?"TestNSTimer.h"


@interface?TestNSTimer?()

@property?(nonatomic,?strong)?NSTimer?*timer;

@end

@implementation?TestNSTimer


-?(instancetype)init?{

????if(self?=?[superinit])?{

????????_timer?=?[NSTimer?scheduledTimerWithTimeInterval:1?target:self?selector:@selector(timeRefresh:)?userInfo:nil?repeats:YES];

????}

????returnself;

}


-?(void)timeRefresh:(NSTimer*)timer?{

????NSLog(@"TimeRefresh...");

}


-?(void)cleanTimer?{

????[_timer?invalidate];

????_timer?=?nil;

}


-?(void)dealloc?{

????[superdealloc];

????NSLog(@"銷毀");

????[self?cleanTimer];

}


@end

在外部調(diào)用時(shí),將其創(chuàng)建后5秒銷毀搔啊。

1

2

3

4

????TestNSTimer?*timer?=?[[TestNSTimer?alloc]init];

????dispatch_after(dispatch_time(DISPATCH_TIME_NOW,?(int64_t)(5?*?NSEC_PER_SEC)),?dispatch_get_main_queue(),?^{

????????[timer?release];

????});

最后的執(zhí)行結(jié)果為

NSTimer打印結(jié)果

可見TestNSTimer對(duì)象并沒有正常釋放柬祠,定時(shí)器仍然在無限的執(zhí)行下去。

我們都知道定時(shí)器使用完畢時(shí)需要將其停止并滯空负芋,但cleanTimer方法到底何時(shí)調(diào)用呢瓶盛?在當(dāng)前類的dealloc方法中嗎?并不是,若將cleanTimer方法調(diào)用在dealloc方法中會(huì)產(chǎn)生如下問題惩猫,當(dāng)前類銷毀執(zhí)行dealloc的前提是定時(shí)器需要停止并滯空芝硬,而定時(shí)器停止并滯空的時(shí)機(jī)在當(dāng)前類調(diào)用dealloc方法時(shí),這樣就造成了互相等待的場(chǎng)景轧房,從而內(nèi)存一直無法釋放拌阴。因此需要注意cleanTimer的調(diào)用時(shí)機(jī)從而避免內(nèi)存無法釋放,如上的解決方案為將cleanTimer方法外漏奶镶,在外部調(diào)用即可迟赃。

1

2

3

4

5

TestNSTimer?*timer?=?[[TestNSTimer?alloc]init];

????dispatch_after(dispatch_time(DISPATCH_TIME_NOW,?(int64_t)(5?*?NSEC_PER_SEC)),?dispatch_get_main_queue(),?^{

????????[timer?cleanTimer];

????????[timer?release];

????});

打印結(jié)果

五、非OC對(duì)象內(nèi)存處理

對(duì)于iOS開發(fā)厂镇,ARC模式已發(fā)揚(yáng)光大多年纤壁,可能很多人早已忘記當(dāng)年retain、release的年代捺信,但ARC的出現(xiàn)并不是說我們完全可以忽視內(nèi)存泄漏的問題酌媒。對(duì)于一些非OC對(duì)象,使用完畢后其內(nèi)存仍需要我們手動(dòng)釋放迄靠。

舉個(gè)例子秒咨,比如常用的濾鏡操作調(diào)節(jié)圖片亮度

CIImage?*beginImage?=?[[CIImage?alloc]initWithImage:[UIImage?imageNamed:@"yourname.jpg"]];

CIFilter?*filter?=?[CIFilter?filterWithName:@"CIColorControls"];

[filter?setValue:beginImage?forKey:kCIInputImageKey];

[filter?setValue:[NSNumber?numberWithFloat:.5]?forKey:@"inputBrightness"];//亮度-1~1

CIImage?*outputImage?=?[filter?outputImage];

//GPU優(yōu)化

EAGLContext?*?eaglContext?=?[[EAGLContext?alloc]?initWithAPI:kEAGLRenderingAPIOpenGLES3];

eaglContext.multiThreaded?=?YES;

CIContext?*context?=?[CIContext?contextWithEAGLContext:eaglContext];

[EAGLContext?setCurrentContext:eaglContext];


CGImageRef?ref?=?[context?createCGImage:outputImage?fromRect:outputImage.extent];

UIImage?*endImg?=?[UIImage?imageWithCGImage:ref];

_imageView.image?=?endImg;

CGImageRelease(ref);//非OC對(duì)象需要手動(dòng)內(nèi)存釋放

在如上代碼中的CGImageRef類型變量非OC對(duì)象,其需要手動(dòng)執(zhí)行釋放操作CGImageRelease(ref)掌挚,否則會(huì)造成大量的內(nèi)存泄漏導(dǎo)致程序崩潰雨席。其他的對(duì)于CoreFoundation框架下的某些對(duì)象或變量需要手動(dòng)釋放、C語言代碼中的malloc等需要對(duì)應(yīng)free等都需要注意吠式。

五陡厘、地圖類處理

若項(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ù)組等。

-?(void)clearMapView{

????self.mapView?=?nil;

????self.mapView.delegate?=nil;

????self.mapView.showsUserLocation?=?NO;

????[self.mapView?removeAnnotations:self.annotations];

????[self.mapView?removeOverlays:self.overlays];

????[self.mapView?setCompassImage:nil];

}

六宜岛、大次數(shù)循環(huán)內(nèi)存暴漲問題

記得有道比較經(jīng)典的面試題长踊,查看如下代碼有何問題:

for(int?i?=?0;?i?<?100000;?i++)?{

????????NSString?*string?=?@"Abc";

????????string?=?[string?lowercaseString];

????????string?=?[string?stringByAppendingString:@"xyz"];

????????NSLog(@"%@",?string);

}

該循環(huán)內(nèi)產(chǎn)生大量的臨時(shí)對(duì)象,直至循環(huán)結(jié)束才釋放萍倡,可能導(dǎo)致內(nèi)存泄漏身弊,解決方法為在循環(huán)中創(chuàng)建自己的autoReleasePool,及時(shí)釋放占用內(nèi)存大的臨時(shí)變量,減少內(nèi)存占用峰值阱佛。


for(int?i?=?0;?i?<?100000;?i++)?{

????????@autoreleasepool?{

????????????NSString?*string?=?@"Abc";

????????????string?=?[string?lowercaseString];

????????????string?=?[string?stringByAppendingString:@"xyz"];

????????????NSLog(@"%@",?string);

????????}

????}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末帖汞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凑术,更是在濱河造成了極大的恐慌翩蘸,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淮逊,死亡現(xiàn)場(chǎng)離奇詭異催首,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)泄鹏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門郎任,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人备籽,你說我怎么就攤上這事舶治。” “怎么了胶台?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵歼疮,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我诈唬,道長(zhǎng)韩脏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任铸磅,我火速辦了婚禮赡矢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘阅仔。我一直安慰自己吹散,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布八酒。 她就那樣靜靜地躺著空民,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羞迷。 梳的紋絲不亂的頭發(fā)上界轩,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音衔瓮,去河邊找鬼浊猾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛热鞍,可吹牛的內(nèi)容都是我干的葫慎。 我是一名探鬼主播衔彻,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼偷办!你這毒婦竟也來了艰额?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤椒涯,失蹤者是張志新(化名)和其女友劉穎悴晰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逐工,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铡溪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泪喊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棕硫。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袒啼,靈堂內(nèi)的尸體忽然破棺而出哈扮,到底是詐尸還是另有隱情,我是刑警寧澤蚓再,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布滑肉,位于F島的核電站,受9級(jí)特大地震影響摘仅,放射性物質(zhì)發(fā)生泄漏靶庙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一娃属、第九天 我趴在偏房一處隱蔽的房頂上張望六荒。 院中可真熱鬧,春花似錦矾端、人聲如沸掏击。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)砚亭。三九已至,卻和暖如春殴玛,著一層夾襖步出監(jiān)牢的瞬間捅膘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工族阅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留篓跛,地道東北人膝捞。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓坦刀,卻偏偏與公主長(zhǎng)得像愧沟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子鲤遥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 為自己學(xué)習(xí)方便沐寺,復(fù)制大神的學(xué)習(xí)性文章放在自己簡(jiǎn)書里,僅作為學(xué)習(xí)方便使用盖奈,如果作者疑此行為侵權(quán)混坞,請(qǐng)隨時(shí)聯(lián)系本人刪除,...
    天地不仁以萬物為芻狗閱讀 4,893評(píng)論 2 3
  • 一厨诸、從AFNet說起 對(duì)于iOS開發(fā)者,網(wǎng)絡(luò)請(qǐng)求類AFNetWorking是再熟悉不過了禾酱,對(duì)于AFNetWorki...
    xh_0129閱讀 374評(píng)論 0 0
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用微酬,...
    LZM輪回閱讀 3,284評(píng)論 0 6
  • 家人很辛苦,很可愛颤陶,很逗比颗管,但也很啰嗦,有時(shí)不搭理他們吧滓走,他們就是“我是你后媽嗎垦江?”或者“一看,就不是親生的”搅方。疫粥。...
    Qaaey姍閱讀 116評(píng)論 0 0
  • 去歲春意時(shí),共邀聚浦滬腰懂。 有興獻(xiàn)辭去梗逮,小酌一杯唔?绣溜!
    古岳言閱讀 164評(píng)論 0 0