ios 內存使用陷阱

在iphone開發過程當中,代碼中的內存泄露咱們很容易用內存檢測工具leaks 檢測出來,並一一改之,但有些是由於ios 的缺陷和用法上的錯誤,leaks 檢測工具並不能檢測出來,你只會看到大量的內存被使用,最後收到didReceiveMemoryWarning,最終致使程序崩潰。如下是開發過程當中遇到的一些問題和網上的一些資料,總結了一下:php

 

1、[UIImage p_w_picpathNamed:]只適合與UI界面中的貼圖的讀取,較大的資源文件應該儘可能避免使用html

用UIImage加載本地圖像最經常使用的是下面三種:ios

1.用p_w_picpathNamed方法shell

[UIImage p_w_picpathNamed:ImageName];

2.用 p_w_picpathWithContentsOfFile 方法數據庫

NSString *thumbnailFile = [NSString stringWithFormat:@"%@/%@.png", [[NSBundle mainBundle] resourcePath], fileName];
UIImage *thumbnail = [UIImage p_w_picpathWithContentsOfFile:thumbnailFile];

3. 用initWithContentsFile方法緩存

UIImage *p_w_picpath = [[UIImage alloc] initWithContentsOfFile:filePath]

 

第一種方法爲常見方法,利用它能夠方便加載資源圖片。用p_w_picpathNamed的方式加載時,會把圖像數據根據它的名字緩存在系統內存中,以提升p_w_picpathNamed方法得到相同圖片的p_w_picpath對象的性能。即便生成的對象被 autoReleasePool釋放了,這份緩存也不釋放。並且沒有明確的釋放方法。若是圖像比較大,或者圖像比較多,用這種方式會消耗很大的內存。iphone

第二種方法加載的圖片是不會緩存的。獲得的對象時autoRelease的,當autoReleasePool釋放時才釋放。ide

第三種方法要手動release掉。不繫統緩存。release後當即釋放,通常用在封面等圖比較大的地方。工具

 

2、 滑動列表的時候,使用UITableView的reuse機制oop

複製代碼

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
     
    static NSString *CellIdentifier = @"Cell"; 
     
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    }

複製代碼

 

dequeueReusableCellWithIdentifier 方法會把隱藏的界面拿來重用,這樣節省不少資源。

 

3、要大量建立局部變量的時候,能夠建立內嵌的autorelease pool來及時釋放內存

複製代碼

int main (int argc, const char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];int i, j;for (i = 0; i < 100; i++ )
{
 NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; for (j = 0; j < 100000; j++ )
    [NSString stringWithFormat:@"1234567890"];//產生的對象是autorelease的。 [loopPool release];
}
[pool release];return (0);
} // main

複製代碼

 

詳細查看:iPhone/Mac Objective-C內存管理教程和原理剖析(一)基本原理

4、頻繁打開和關閉SQLite,致使內存不斷的增加

SQLite的數據庫本質上來說就是一個磁盤上的文件,頻繁打開和關閉是很耗時和浪費資源的,能夠設置SQLite的長鏈接方式;避免頻繁的打開和關閉數據庫;

 

5、在UITableView 的cellForRowAtIndexPath 代理中不要使用 stringWithFormat 方法

定義一個字符串變量有不少方法,最簡單的就是 NSString *str = @「abc」, 還有initWithString、stringWithFormat和stringWithCString等等。大量的字符操做時,不一樣的方法消耗不一樣的內存。

如下測試代碼轉自:http://www.cocoachina.com/bbs/read.php?tid-17652-fpage-9.html

複製代碼

//
- ()testStringSpeed:(*pool= testi,testnum= c,tm=(testi=;testi<testnum;testi++*beg= i,n=(i=;i<n;i++
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            =+=,[textField stringValue],testi+,[textField stringValue],()tm/

複製代碼

 

因爲stringWithFormat 即耗時又耗內存,因此在cellForRowAtIndexPath 繪製cell 的時消耗大量內存和時間,形成界面滑動不流暢。

 

6、關於 colorWithPatternImage 的內存泄露

self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage p_w_picpathNamed:@"bg.png"]];

此方法用圖片來設置view的背景顏色,可是某些設備上會致使內存泄露,詳細查看:

http://blog.csdn.net/cococoolwhj/article/details/6942981

http://www.cocoaintheshell.com/2011/01/colorwithpatternp_w_picpath-memory-usage/

相關文章
相關標籤/搜索