構(gòu)建內(nèi)存高效的應(yīng)用

作者:Thomas Hanning宴凉,原文鏈接,原文日期:2015/08/06
譯者:BridgeQ恬口;校對(duì):lfb-CD校读;定稿:shanks

近年來(lái),移動(dòng)設(shè)備的性能越來(lái)越強(qiáng)大祖能。然而歉秫,同桌面電腦相比,性能上總還是有一段不小的差距养铸。同時(shí)雁芙,用戶界面和交互設(shè)計(jì)的要求也越來(lái)越高。所以钞螟,為移動(dòng)設(shè)備編寫內(nèi)存高效的應(yīng)用仍然很有必要兔甘。

什么是內(nèi)存高效的應(yīng)用

通俗點(diǎn)講,內(nèi)存高效的應(yīng)用是指:僅使用必要的內(nèi)存消耗并盡量減少內(nèi)存消耗鳞滨;用戶界面設(shè)計(jì)使用低內(nèi)存消耗的框架裂明。當(dāng)然,一個(gè)復(fù)雜度更高的應(yīng)用也肯定需要更高的內(nèi)存消耗。

接下來(lái)我們首先來(lái)回顧一小段歷史:

自動(dòng)引用計(jì)數(shù)(ARC:Automatic Reference Counting)

在早期的 iOS 開發(fā)中闽晦,內(nèi)存管理扮演著非常重要的角色。因?yàn)閭鹘y(tǒng)的垃圾回收機(jī)制對(duì)于移動(dòng)平臺(tái)來(lái)說(shuō)是非常低效的提岔,所以蘋果把內(nèi)存管理的責(zé)任交給了開發(fā)者仙蛉,你需要通過(guò)手動(dòng)的方式來(lái)增加或減少一個(gè)對(duì)象的引用計(jì)數(shù)。

通過(guò)這種方式碱蒙,你可以寫出內(nèi)存管理非常高效的應(yīng)用荠瘪,因?yàn)閷?duì)象不再使用時(shí)就立刻被銷毀了。但另一方面赛惩,很多時(shí)候手動(dòng)管理內(nèi)存并不容易哀墓,也經(jīng)常產(chǎn)生一些不易被發(fā)現(xiàn)的bug。所以喷兼,這并不是解決內(nèi)存管理問題的最好辦法篮绰。

新的解決方案是在 iOS 5 中被提出的:自動(dòng)引用計(jì)數(shù)(ARC)。從此之后季惯,控制引用計(jì)數(shù)的命令會(huì)在編譯期間被自動(dòng)加入而無(wú)需手動(dòng)編寫吠各。這樣帶來(lái)的好處是:一方面能編寫出內(nèi)存高效的代碼,另一方面讓開發(fā)者不用再關(guān)心內(nèi)存管理問題勉抓。這個(gè)解決方案非常棒贾漏,以至于 Mac OS X 的應(yīng)用程序也開始使用 ARC 來(lái)管理內(nèi)存。

不過(guò)藕筋,盡管你不需要再關(guān)心引用計(jì)數(shù)了纵散,但還是需要你去關(guān)心一些其他內(nèi)存管理相關(guān)的知識(shí)點(diǎn)。

選擇合適的部署版本

正如前文所說(shuō)隐圾,不同的需求意味著應(yīng)用的內(nèi)存消耗也不盡相同伍掀,除此之外,不同的需求還意味著應(yīng)用適應(yīng)于不同的部署版本(應(yīng)用運(yùn)行所支持的最低系統(tǒng)版本)翎承。舉個(gè)栗子硕盹,如果你的部署版本是 iOS 5,那么你就不能忘了要支持第一代 iPad 產(chǎn)品叨咖,它的內(nèi)存大小僅僅是 256 MB瘩例。雖然,支持盡可能多的版本是一種不錯(cuò)的選擇甸各,但是垛贤,在你所支持的版本上為用戶帶來(lái)良好的用戶體驗(yàn)才是更重要的。所以趣倾,當(dāng)你想支持一些舊設(shè)備的時(shí)候聘惦,在設(shè)計(jì)階段就要仔細(xì)考慮內(nèi)存消耗問題。

下面列舉了不同系統(tǒng)版本所支持的一些舊設(shè)備:

  • iOS 9: iPhone 4S / iPad 2 / iPad Mini 1
  • iOS 8: iPhone 4S / iPad 2 / iPad Mini 1
  • iOS 7: iPhone 4 / iPad 2 / iPad Mini 1
  • iOS 6: iPhone 3GS / iPad 2/ iPad Mini 1
  • iOS 5: iPhone 3GS / iPad 1 / –

由于蘋果的生態(tài)系統(tǒng)更新速度比較快儒恋,所以支持最新的兩代操作系統(tǒng)版本是一個(gè)很好的選擇善绎。除了內(nèi)存方面的問題黔漂,支持過(guò)多的系統(tǒng)版本還會(huì)帶來(lái)開發(fā)和測(cè)試等諸多方面的問題。

圖片資源

在移動(dòng)應(yīng)用中禀酱,圖片是非常重要的資源炬守。然而,圖片也通常代表著高內(nèi)存消耗剂跟。在處理圖片資源的時(shí)候减途,有以下兩點(diǎn)需要注意:

  • 首先,圖片應(yīng)該有合適的尺寸曹洽。如果你有一個(gè)表格視圖鳍置,上面需要 100 × 100 像素的圖片,而你卻使用 1000 × 1000 像素的圖片送淆,這一定是一個(gè)非常糟糕的作法税产,性能會(huì)受到非常大的影響。如果你是通過(guò)請(qǐng)求服務(wù)器獲取的圖片坊夫,那么服務(wù)器也應(yīng)該進(jìn)行處理以提供合適尺寸的圖片砖第。
  • 其次,一定要保證圖片只是在需要使用的時(shí)候才被加載环凿。舉個(gè)栗子梧兼,表格視圖里的圖片只有當(dāng)單元格顯示出來(lái)的時(shí)候才需要被加載,也就是說(shuō)單元格是可以循環(huán)利用的智听。想象一下羽杰,如果你的表格視圖有 5000 個(gè)單元格并在進(jìn)入屏幕的時(shí)候全部被加載,這樣的話到推,即使你的應(yīng)用沒有因?yàn)閮?nèi)存壓力而崩潰考赛,用戶體驗(yàn)也一定會(huì)非常的糟糕。你自定義的視圖也同樣應(yīng)該遵守這一原則莉测。再舉個(gè)栗子颜骤,如果你在開發(fā)一個(gè)相冊(cè)類應(yīng)用,不要一口氣把所有圖片都加載完捣卤,你只需加載顯示在屏幕上的那些圖片就夠了忍抽。這種技術(shù)也通常被稱作延遲加載(lazy loading)。

延遲加載(lazy loading)

延遲加載技術(shù)的主旨就是盡可能晚地去加載資源董朝,這樣會(huì)帶來(lái)以下兩點(diǎn)優(yōu)勢(shì):

  • 可以更好地來(lái)分配不同的加載時(shí)間
  • 可以避免加載那些可能不需要的資源

那么在 iOS 開發(fā)中如何使用延遲加載技術(shù)呢鸠项?正如前文提到的,表格視圖就是一個(gè)很好的使用延遲加載技術(shù)的栗子子姜。另一種使用延遲加載的方法是使用lazy關(guān)鍵字來(lái)修飾屬性祟绊。想象一下你需要一個(gè)包含所有產(chǎn)品的數(shù)組,當(dāng)用戶進(jìn)行一定交互時(shí)需要使用到它們。

var products: [Products] = modelClass.loadProducts()

如上代碼牧抽,這個(gè)數(shù)組即使在用戶沒有進(jìn)行任何交互的情況下仍然會(huì)被加載嘉熊,這是一種內(nèi)存浪費(fèi)。如果加上lazy關(guān)鍵字進(jìn)行修飾阎姥,那么只有在用戶第一次訪問數(shù)組的時(shí)候它才會(huì)初始化记舆。

lazy var products: [Products] = modelClass.loadProducts()

即使只是一些小的數(shù)組和變量,合理地使用延遲加載技術(shù)也能節(jié)省很大一部分內(nèi)存呼巴。

視圖控制器和循環(huán)引用

在所有內(nèi)存問題中最壞的一種情況就是視圖控制器不再需要的時(shí)候卻沒有被釋放,出現(xiàn)這種情況最通常的原因是循環(huán)引用御蒲。試想一下衣赶,現(xiàn)在有一個(gè)控制器 A,它擁有一個(gè)控制器 B 作為它的子控制器厚满,而且府瞄,控制器 B 還有一個(gè)指向控制器 A 的引用,這樣它們都互相強(qiáng)引用著對(duì)方碘箍。

現(xiàn)在遵馆,即使控制器 A 從屏幕中離開,兩個(gè)控制器也不會(huì)被釋放丰榴,因?yàn)樗鼈冞€都強(qiáng)引用著對(duì)方货邓。要避免這種情況你可以使用weak關(guān)鍵字。舉個(gè)栗子四濒,想要將控制器 A 設(shè)置為控制器 B 的代理换况,正確的屬性聲明應(yīng)該如下所示:

weak var delegate: DelegateType?

如果想檢查控制器是否被正確釋放,可以在控制器的deinit方法中打印消息來(lái)查看盗蟆,代碼如下:

deinit {
     println("deinit")
}

接下來(lái)你就可以通過(guò)在控制臺(tái)中觀察戈二,是否有輸出來(lái)檢查控制器對(duì)象是否被正確釋放。比如說(shuō)喳资,當(dāng)你的控制器是被導(dǎo)航控制器通過(guò)push方法展現(xiàn)出來(lái)的時(shí)候觉吭,如果你點(diǎn)擊了導(dǎo)航條上的返回按鈕,控制器應(yīng)該被釋放并且在控制臺(tái)中輸出信息仆邓。

監(jiān)測(cè)你的內(nèi)存使用量

我們通常是在項(xiàng)目開發(fā)的最后階段才發(fā)現(xiàn)內(nèi)存管理的很糟糕鲜滩,不幸的是,這樣已經(jīng)太晚了宏赘。所以在項(xiàng)目開發(fā)過(guò)程中绒北,經(jīng)常對(duì)內(nèi)存使用量進(jìn)行監(jiān)測(cè)是非常重要的。你只需在一臺(tái)真機(jī)上運(yùn)行你的應(yīng)用察署,然后點(diǎn)擊Xcode中調(diào)試選項(xiàng)卡下的Memory闷游。

總結(jié)

內(nèi)存管理在移動(dòng)開發(fā)領(lǐng)域是一個(gè)非常重要的話題。如果你使用了過(guò)多的內(nèi)存消耗,應(yīng)用就會(huì)變慢甚至可能崩潰脐往。相反休吠,如果你認(rèn)真對(duì)待內(nèi)存管理問題,你就會(huì)構(gòu)建出內(nèi)存高效的應(yīng)用业簿。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瘤礁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梅尤,更是在濱河造成了極大的恐慌柜思,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巷燥,死亡現(xiàn)場(chǎng)離奇詭異赡盘,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)缰揪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門陨享,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人钝腺,你說(shuō)我怎么就攤上這事抛姑。” “怎么了艳狐?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵定硝,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我僵驰,道長(zhǎng)喷斋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任蒜茴,我火速辦了婚禮星爪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粉私。我一直安慰自己顽腾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布诺核。 她就那樣靜靜地躺著抄肖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窖杀。 梳的紋絲不亂的頭發(fā)上漓摩,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音入客,去河邊找鬼管毙。 笑死腿椎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的夭咬。 我是一名探鬼主播啃炸,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼卓舵!你這毒婦竟也來(lái)了南用?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤掏湾,失蹤者是張志新(化名)和其女友劉穎裹虫,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體融击,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恒界,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砚嘴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涩拙,死狀恐怖际长,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情兴泥,我是刑警寧澤工育,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站搓彻,受9級(jí)特大地震影響如绸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜旭贬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一怔接、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧稀轨,春花似錦扼脐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至佣谐,卻和暖如春肚吏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狭魂。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工罚攀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留党觅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓坞生,卻偏偏與公主長(zhǎng)得像仔役,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子是己,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)又兵、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,120評(píng)論 4 61
  • 2017年10月9日如是家人溫玲卒废,種種子第70天 發(fā)心:我今不是為了我個(gè)人而聞思修沛厨,而是為了六道輪回一切如母有情眾...
    溫馨霏玲閱讀 211評(píng)論 2 4
  • 你看不起他! 但沒辦法摔认,這就是特權(quán)逆皮! 要不你努力超越他! 要不你就被長(zhǎng)期壓制参袱,無(wú)法反抗电谣!
    繁華似簡(jiǎn)閱讀 154評(píng)論 0 0
  • Appium適配Android7.0以上版本 測(cè)試機(jī)型: 華為榮耀V9 安卓版本: Android7.0 appi...
    米洛丶閱讀 1,155評(píng)論 9 2