自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

iOS 內(nèi)存管理:內(nèi)存優(yōu)化

存儲 存儲軟件 iOS
所謂的內(nèi)存優(yōu)化,在設(shè)計(jì)程序的過程中,我們要在保證程序運(yùn)行效率的前提下,盡量壓縮程序運(yùn)行時(shí)所占用的內(nèi)存。無論硬件設(shè)備的內(nèi)存有多大,程序運(yùn)行時(shí)占用內(nèi)存越少越好。下面我將介紹在開發(fā)項(xiàng)目過程中,一些優(yōu)化內(nèi)存的方法。

所謂的內(nèi)存優(yōu)化,在設(shè)計(jì)程序的過程中,我們要在保證程序運(yùn)行效率的前提下,盡量壓縮程序運(yùn)行時(shí)所占用的內(nèi)存。無論硬件設(shè)備的內(nèi)存有多大,程序運(yùn)行時(shí)占用內(nèi)存越少越好。下面我將介紹在開發(fā)項(xiàng)目過程中,一些優(yōu)化內(nèi)存的方法。

1.關(guān)于UITableView

在項(xiàng)目開發(fā)中,UITableView 是用的比較多的一個(gè)視圖控件。如果能夠?qū)?UITableView 的使用做好優(yōu)化,程序的性能將提高很多。

(1)善于使用UITableViewCell的重用機(jī)制

重用機(jī)制:這種機(jī)制下系統(tǒng)默認(rèn)有一個(gè)可變數(shù)組 NSMutableArray* visiableCells,用來保存當(dāng)前顯示的cell。一個(gè)可變字典 NSMutableDictnery* reusableTableCells ,用來保存可重復(fù)利用的cell。UITableView 只會創(chuàng)建一屏幕的cell,放在 visiableCells中。每當(dāng)cell滑出屏幕,就會放到 reusableTableCells 中,當(dāng)要顯示某一個(gè)位置的cell時(shí),先去 reusableTableCells 中取,如果有,直接取來用;如果沒有,就會創(chuàng)建。這樣極大減少了內(nèi)存的開銷。

[[237457]]

在iOS 6之后,在UITableView和UICollectionView中除了可以復(fù)用cell,還可以復(fù)用各個(gè)Section的Header和Footer??梢夾pple一直在不斷優(yōu)化。在項(xiàng)目開發(fā)中,我們需要給 UITableViewCells、 UICollectionViewCells、UITableViewHeaderFooterViews設(shè)置正確的 reuseIdentifier。當(dāng)有多類cell需要復(fù)用是,我們可以根據(jù) reuseIdentifier 區(qū)分。我們可以在Xcode中設(shè)置,如下圖:

下面是一個(gè)簡單的cell復(fù)用的示例:

  1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
  2.     static NSString *cellIdentifier = nil; 
  3.     UITableViewCell *cell = nil; 
  4.      
  5.     cellIdentifier = @"你的xib文件視圖中標(biāo)注的reuseIdentifier"
  6.     cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];    //根據(jù)identifier復(fù)用cell 
  7.      
  8.     //如果沒有對應(yīng)的cell,創(chuàng)建cell 
  9.     if(!cell){ 
  10.         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 
  11.     } 
  12.      
  13.     return cell; 

復(fù)用cell是一個(gè)很好的機(jī)制,但是使用不當(dāng)也會出現(xiàn)問題,也就是所謂的復(fù)用重疊問題??聪旅娲a:

我本打算將偶數(shù)行的設(shè)置為藍(lán)色,基數(shù)行為默認(rèn)顏色,并將cell的內(nèi)容設(shè)置為行數(shù),加以區(qū)分。結(jié)果如圖:

從上圖可以看出,開始初始化的13~14個(gè)cell正常,但是當(dāng)滑動(dòng)tableview時(shí),就出現(xiàn)了問題,有的基數(shù)行cell也變?yōu)榱怂{(lán)色。這是因?yàn)?,下面的cell基本都是復(fù)用的,當(dāng)沒有顯示指定cell的屬性時(shí),它就會使用已經(jīng)創(chuàng)建過的cell的屬性,導(dǎo)致有的藍(lán)色有的白色。解決辦法就是像下面這樣寫:

切記:當(dāng)對多種cell賦予屬性時(shí),一定不能寫在 if (!cell){} 里面,避免復(fù)用出現(xiàn)問題。

(2)優(yōu)化UITableViewCell高度計(jì)算

UITableView有兩個(gè)很重要的回調(diào)方法:tableView:cellForRowAtIndexPath:和tableView:heightForRowAtIndexPath:。很多人認(rèn)為,在初始化tableview時(shí),會先調(diào)用前者進(jìn)行創(chuàng)建,然后再調(diào)用后者進(jìn)行布局和屬性設(shè)置。然而并非如此。真實(shí)的情況是這樣的:UITableView是繼承自UIScrollView的,需要先確定它的contentSize及每個(gè)Cell的位置,然后才會把重用的Cell放置到對應(yīng)的位置。所以事實(shí)上,UITableView的回調(diào)順序是先多次調(diào)用 tableView:heightForRowAtIndexPath: 以確定contentSize及Cell的位置,然后才會調(diào)用 tableView:cellForRowAtIndexPath:,從而來顯示在當(dāng)前屏幕的Cell。

舉個(gè)例子:如果現(xiàn)在要顯示20個(gè)Cell,當(dāng)前屏幕顯示5個(gè)。那么刷新(reload)UITableView時(shí),UITableView會先調(diào)用20次 tableView:heightForRowAtIndexPath: 方法,然后調(diào)用5次tableView:cellForRowAtIndexPath:方法;滾動(dòng)屏幕時(shí),每當(dāng)Cell滾入屏幕,都會調(diào)用一次tableView:heightForRowAtIndexPath:、tableView:cellForRowAtIndexPath:方法。

所以,對于UITableViewCell的高度計(jì)算的優(yōu)化,就是對這兩個(gè)函數(shù)的處理。至于如何優(yōu)化@我就叫Sunny怎么了寫了一篇很好的文章去介紹。我就不多說了。

(3) 懶加載(延遲加載)

懶加載并不是減少了程序內(nèi)存消耗,而是將加載對象的時(shí)間推遲,在使用到對象的時(shí)候在對其進(jìn)行初始化。例如一個(gè)UITableView一共有20行,但是屏幕只顯示5行數(shù)組。那么在初始化tableview的時(shí)候,可以只先加載5行數(shù)據(jù),另外15行等到顯示的時(shí)候再去加載。這樣可以減少初始化tableview時(shí)所需要的內(nèi)存。(這樣說有點(diǎn)牽強(qiáng),因?yàn)閷?shí)時(shí)加載會影響tableview的流暢度,但是大體就是這個(gè)意思 ><)

2.關(guān)于圖片的處理

圖片在內(nèi)存中會占很大開銷,如果適當(dāng)?shù)奶幚韴D片,會減少很多內(nèi)存的消耗。

(1)緩存圖片

常見的從bundle中加載圖片的方式有兩種,一個(gè)是用imageNamed,二是用imageWithContentsOfFile,***種比較常見一點(diǎn)。

imageNamed的優(yōu)點(diǎn)是當(dāng)加載時(shí)會緩存圖片。imageNamed的文檔中這么說:

這個(gè)方法用一個(gè)指定的名字在系統(tǒng)緩存中查找并返回一個(gè)圖片對象如果它存在的話。如果緩存中沒有找到相應(yīng)的圖片,這個(gè)方法從指定的文檔中加載然后緩存并返回這個(gè)對象。

也就是說,imageNamed方法加載的圖片,會對圖片進(jìn)行緩存。而 imageWithContentsOfFile 方法不會。

所以,如果要加載的圖片比較小,而且會反復(fù)使用,這種情況選擇用 imageNamed;如果要加載一個(gè)大圖片,而且是一次性使用,那就使用 imageWithContentsOfFile,沒必要浪費(fèi)內(nèi)存去緩存它。

代碼示例:

(2)調(diào)整圖片大小

我們經(jīng)常從網(wǎng)絡(luò)獲取圖片或者從本地bundle獲取圖片,然后加載到 UIImageView 中。在加載圖片時(shí),應(yīng)盡量保證圖片大小和 UIImageView 大小相同。因?yàn)樵谶\(yùn)行中縮放圖片很耗費(fèi)資源,如果 UIImageView 嵌套在 UIScrollView 或者 UITableView中,會更耗費(fèi)資源。

對于從本地bundle中加載的圖片,我們可以事先件圖片處理好。對于從網(wǎng)絡(luò)下載的圖片,在下載完成后,我們需要對圖片進(jìn)行縮放,然后再加載。

(3)代碼渲染 or 直接獲取

前面已經(jīng)說過,用代碼去渲染一張圖片會使圖片占用內(nèi)存翻倍。但是用代碼去繪制圖片,能夠很好的去控制圖片,并且能夠做出很多漂亮的效果,前提是犧牲一部分內(nèi)存;那如果所有圖片都從bundle中加載呢?那會使bundle的體積增大,同時(shí)不能夠用代碼去靈活處理圖片的效果。

所以,在開發(fā)過程中,是代碼渲染圖片,還是從bundle獲取圖片,需要做一個(gè)權(quán)衡。

3.數(shù)據(jù)處理

在項(xiàng)目開發(fā)中,我們會使用到各種格式的數(shù)據(jù),例如 JSON、XML 等。還有各種各樣的數(shù)據(jù)結(jié)構(gòu),例如數(shù)組、鏈表、字典、集合等。使用正確的數(shù)據(jù)格式和使用正確的數(shù)據(jù)結(jié)構(gòu),會減少我們的資源消耗。

(1)選擇正確的數(shù)據(jù)格式

App與網(wǎng)絡(luò)進(jìn)行交互時(shí),常常采用 JSON 或者 XML 類型的數(shù)據(jù)格式。

JSON 是一種輕量級的數(shù)據(jù)交換格式,具有良好的可讀和便于快速編寫的特性。解析 JSON 會比 XML更快,但是 JSON 傳輸?shù)臄?shù)據(jù)比較小。

XML 是一種重量級的數(shù)據(jù)交換格式,適用于很大的數(shù)據(jù)傳輸。當(dāng)數(shù)據(jù)量較大時(shí),使用 XML 數(shù)據(jù)格式,會極大減少內(nèi)存消耗,增加性能。

另外,盡量避免數(shù)據(jù)多次轉(zhuǎn)化。例如tableview中需要以數(shù)組的形勢去賦值。那么服務(wù)器盡量返回?cái)?shù)組類型。如果返回 JSON 類型,在去轉(zhuǎn)換為 NSArray 類型,也會增加開銷。

(2)選擇正確的數(shù)據(jù)結(jié)構(gòu)

不同的數(shù)據(jù)結(jié)構(gòu),處理數(shù)據(jù)的速度是不同的。

數(shù)組 NSArray NSMutableArray:有序的一組值。使用索引來查詢很快,使用值查找很慢, 插入/刪除很慢。

字典 NSDictionary NSMutableDictionary:存儲鍵值對。用鍵來查找比較快。

集合 NSSet NSMutableSet:無序的一組值。用值來查找很快,插入/刪除很快。

4.View的處理

(1)避免使用過于復(fù)雜的xib

在目前很多項(xiàng)目開發(fā)中,還經(jīng)常用到 xib。當(dāng)加載一個(gè) xib 時(shí),所有的內(nèi)容都會放到內(nèi)存里,包括任何圖片。如果 xib 文件過于龐大,會占用很多內(nèi)存。xib 與 storyboard 不同,xib即使暫時(shí)用不到,view也會存在于內(nèi)存里;storyboard 僅在需要時(shí)實(shí)例化一個(gè)view controller。

而且設(shè)置view屬性時(shí),盡可能的把 opaque 屬性設(shè)置為YES(不透明)。這樣會提高渲染系統(tǒng)優(yōu)化一些渲染過程和提高性能。

(2)正確設(shè)置View的背景

設(shè)置UIView的背景圖片主要有兩種方式:

使用 UIColor的 colorWithPatternImage 來設(shè)置背景色;

給 UIView 添加 UIImageView 子視圖。

***種方式,適合使用小圖平鋪創(chuàng)建背景,能更快渲染也不會會費(fèi)很多內(nèi)存。例如使用一個(gè)10x10的像素大小重復(fù)背景。

第二種方式,適合于使用大圖,即整張圖片來設(shè)置背景。如果使用 colorWithPatternImage 會消耗太多內(nèi)存從而收到內(nèi)存警告導(dǎo)致應(yīng)用程序突然崩潰。而使用 UIImageView 會節(jié)約不少內(nèi)存。

(3)設(shè)定Shadow Path

如果用下面代碼給 view.layer 添加一個(gè)shadow:

這會使Core Animation 不得不在后臺得出圖形并加好陰影之后再去渲染,這會開銷很大。

如果使用shadowPath則會避免這種問題:

5.合理使用Autorelease Pool

NSAutoreleasePool負(fù)責(zé)釋放block中的autoreleased objects。一般情況下它會自動(dòng)被UIKit調(diào)用。但是有些狀況下也需要手動(dòng)去創(chuàng)建它。

假如創(chuàng)建很多臨時(shí)對象,你會發(fā)現(xiàn)內(nèi)存一直在減少直到這些對象被release的時(shí)候。這是因?yàn)橹挥挟?dāng)UIKit用光了autorelease pool的時(shí)候memory才會被釋放。

但是如果自己定義 @autoreleasepool ,在里面創(chuàng)建臨時(shí)對象,可以避免這個(gè)問題:

6.正確處理緩存

緩存可以分為內(nèi)存緩存和磁盤緩存。在項(xiàng)目開發(fā)過程中,我們經(jīng)常會對一些圖片、聲音、數(shù)據(jù)進(jìn)行緩存。合理利用緩存機(jī)制,會大大提高程序的性能,提高APP的流暢性。例如被廣為使用的 SDWebImage,它使用的緩存機(jī)制是這樣的:

(1)先根據(jù)查看內(nèi)存緩存,如果有直接獲取。

(2)如果內(nèi)存沒有,從磁盤緩存獲取。

(3)如果磁盤緩存也沒有,直接通過URL從網(wǎng)絡(luò)下載。

當(dāng)然這只是一個(gè)簡單的描述,更加詳細(xì)請看@南峰子_老驢的一篇SDWebImage實(shí)現(xiàn)分析。

合理處理緩存,能夠提高程序的性能,不用每次都從網(wǎng)絡(luò)獲取數(shù)據(jù)。但是也不能什么都存入緩存,這會消耗很多內(nèi)存和磁盤空間。所以應(yīng)合理使用緩存機(jī)制。

小結(jié)

以上,是我對于內(nèi)存優(yōu)化的一些理解。在寫這篇文章過程中,參考了很多大牛的文章。對于一名在校應(yīng)屆本科生來說,我對于oc的理解還很淺薄,如果有錯(cuò)誤或者有需要添加的地方,希望大家能夠指出。我會加以改正并學(xué)習(xí)。

 

責(zé)任編輯:武曉燕 來源: bool周
相關(guān)推薦

2017-03-07 10:15:35

iOS內(nèi)存管理開發(fā)

2011-07-28 10:01:19

IOS 內(nèi)存優(yōu)化

2015-03-13 09:30:23

iOS內(nèi)存管理

2011-07-21 14:42:45

iOS UIViewCont 內(nèi)存

2016-04-11 09:30:49

內(nèi)存管理ios開發(fā)

2017-02-09 21:24:22

iOS內(nèi)存管理

2024-12-31 00:00:15

2015-06-25 09:47:20

iOS內(nèi)存管理

2013-10-11 17:32:18

Linux運(yùn)維內(nèi)存管理

2014-03-12 09:37:22

內(nèi)存管理autoreleaseautorelease

2010-08-10 10:00:57

Flex內(nèi)存

2017-02-14 17:00:39

iOSApp內(nèi)存優(yōu)化

2011-08-05 16:41:48

iOS 隊(duì)列 內(nèi)存

2016-03-03 10:07:39

ios內(nèi)存管理面試總結(jié)

2011-07-21 17:40:43

iOS 多核 內(nèi)存

2023-10-18 13:31:00

Linux內(nèi)存

2022-07-05 08:41:03

Redis保存大數(shù)據(jù)

2013-10-12 13:01:51

Linux運(yùn)維內(nèi)存管理

2010-08-10 10:17:44

Flex內(nèi)存

2023-10-12 07:43:45

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號