內(nèi)存警告的處理
1、首先需要檢查循環(huán)應(yīng)用的問題
① 設(shè)置代理時(shí)注意要使用弱引用淮椰。
② block使用時(shí)五慈,函數(shù)內(nèi)部涉及到外部的引用需要用weak修飾來打破環(huán)。但是用weak修飾也有缺陷主穗,如果block內(nèi)部是延時(shí)操作或者說異步操作泻拦,很有可能在使用數(shù)據(jù)的時(shí)候,數(shù)據(jù)的內(nèi)存就已經(jīng)被回收了忽媒,怎么解決呢聪轿?我們放到后面講。
③ NSTimer的使用
2猾浦、大量的變量占據(jù)了較大內(nèi)存
需要放到@autoreleasepool自動(dòng)釋放池陆错。
3、清除不需要的視圖
清除前判斷視圖已經(jīng)被創(chuàng)建了 && 視圖沒有出現(xiàn)在window上金赦,就可以清除了音瓷。還有當(dāng)前vc中的一些變量都可以置空,不過前提是要記得用懶加載夹抗,這樣在置空后還可以加載回來
4绳慎、applicationDidReceiveMemoryWarning
在AppDelegate的applicationDidReceiveMemoryWarning可以做一些全局的處理,比方說一些單例可以直接置空.
5漠烧、檢查有使用圖片的code
不要給用戶展示過大的原圖杏愤,如果一定要展示使用imageWithContentsOfFile(僅加載圖片,不緩存)已脓,在展示后手動(dòng)置空珊楼。如果使用了SDWebImageView,也可以通過置空sharedImageCache緩存在內(nèi)存的圖片
6度液、野指針的檢查(僵尸對(duì)象)
7厕宗、銷毀持有大量對(duì)象的容器類變量
在后臺(tái)銷毀該類型對(duì)象画舌,銷毀方法:將要銷毀的對(duì)象捕獲到block中,放到異步的后臺(tái)隊(duì)列隨便發(fā)個(gè)消息來避免警告已慢,就可以讓對(duì)象在后臺(tái)銷毀了
定時(shí)器的應(yīng)用
NSTimer使用注意事項(xiàng)
- 說明:NSTimer設(shè)置target = self并且是反復(fù)使用的時(shí)候曲聂,很容易和當(dāng)前類形成循環(huán)引用,在不使用的時(shí)候佑惠,記得注銷計(jì)時(shí)器后賦值為nil朋腋,但是這個(gè)很難保證他人使用自己的類會(huì)記得,因此我們可以提前做一下處理膜楷。
** 在dealloc時(shí)invalidate是無效的旭咽,因?yàn)槿绻霈F(xiàn)循環(huán)引用,該viewcontroller是不會(huì)進(jìn)入到dealloc階段把将,所以也無法注銷該計(jì)時(shí)器 ** - 特殊情況:在iOS10后可以調(diào)用scheduledTimerWithTimeInterval:repeats:blocks來實(shí)現(xiàn).使用上面方法的時(shí)候要注意先定義一個(gè)弱引用weakSelf指向self (__weak typeOf(self)weakSelf = self)轻专,但是在block使用weakSelf有個(gè)問題忆矛,這個(gè)self不會(huì)為計(jì)數(shù)器保留察蹲,而且有可能在self內(nèi)存回收后才執(zhí)行,這就會(huì)引起報(bào)錯(cuò)了催训。所以我們?cè)趬K開始執(zhí)行時(shí)洽议,立即生成strong引用(MyObject *strongSelf = weakSelf)那在iOS10以前要怎么處理呢?我們可以為NSTimer寫個(gè)分類漫拭,在@seletor()里面實(shí)現(xiàn)block的調(diào)用方法亚兄,block作為參數(shù)在userInfo傳遞過去
- 優(yōu)勢(shì):能夠繼承使用,比較靈活
- 弊端:依托于RunLoop采驻,準(zhǔn)確性容易受RunLoop影響审胚,同時(shí)也容易造成內(nèi)存泄漏
CADisplayLink
- 優(yōu)勢(shì):根據(jù)屏幕刷新幀率來觸發(fā)事件,因此時(shí)間是比較準(zhǔn)確的一種計(jì)時(shí)器礼旅,適合做UI刷新的工作膳叨,過渡比較順滑
- 劣勢(shì):Selector事件如果大于間隔時(shí)間,容易導(dǎo)致掉幀痘系;不能被繼承使用菲嘴;事件處理的間隔只能是屏幕刷新間隔的倍數(shù);如果CPU負(fù)荷太大,會(huì)影響到屏幕刷新的幀率汰翠,從而影響事件的調(diào)用
dispatch_source_t
- 說明:這是GCD的一個(gè)源對(duì)象龄坪,使用的時(shí)候必須設(shè)置為成員變量,否則會(huì)在創(chuàng)建后立刻釋放复唤。GCD創(chuàng)建的Timer如果處于suspend掛起狀態(tài)健田,需要resume才能cancel,否則容易造成內(nèi)存泄漏佛纫。
- 劣勢(shì):雖然不受RunLoop影響抄课,但是如果有其他事件阻塞了全部的線程唱星,也會(huì)影響該計(jì)時(shí)器
** PS:記得block傳參時(shí)要聲明copy,理由不在這里講了跟磨。*
Method Swizzling應(yīng)該在+load()還是+initialize()執(zhí)行间聊,并說明理由
應(yīng)該在+load()執(zhí)行。
+load()是在類初始化加載的時(shí)候就會(huì)調(diào)用抵拘,+initialize()則是在第一次調(diào)用該類的類方法或者生成實(shí)例的時(shí)候調(diào)用哎榴,前者比后者要先執(zhí)行。由于Method Swizzling是會(huì)影響全局的狀態(tài)僵蛛,并且這個(gè)操作不是原子性的尚蝌,因此最小競(jìng)爭(zhēng)的條件就尤其重要,在+load()就能避免很多問題充尉。但是在執(zhí)行+load()的時(shí)候飘言,應(yīng)用的線程是阻塞的,這也是為什么Method Swizzling要盡可能少用的原因驼侠。