ios 內存使用陷阱


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

 

一、[UIImage imageNamed:]只適合與UI界面中的貼圖的讀取,較大的資源文件應該盡量避免使用

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

1.用imageNamed方法

[UIImage imageNamed:ImageName];

2.用 imageWithContentsOfFile 方法

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

3. 用initWithContentsFile方法

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

 

第一種方法為常見方法,利用它可以方便加載資源圖片。用imageNamed的方式加載時,會把圖像數據根據它的名字緩存在系統內存中,以提高imageNamed方法獲得相同圖片的image對象的性能。即使生成的對象被 autoReleasePool釋放了,這份緩存也不釋放。而且沒有明確的釋放方法。如果圖像比較大,或者圖像比較多,用這種方式會消耗很大的內存。

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

第三種方法要手動release掉。不系統緩存。release后立即釋放,一般用在封面等圖比較大的地方。

 

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

- (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 方法會把隱藏的界面拿來重用,這樣節省很多資源。

 

三、要大量創建局部變量的時候,可以創建內嵌的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內存管理教程和原理剖析(一)基本原理

四、頻繁打開和關閉SQLite,導致內存不斷的增長

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

 

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

定義一個字符串變量有很多方法,最簡單的就是 NSString *str = @“abc”, 還有initWithString、stringWithFormat和stringWithCString等等。大量的字符操作時,不同的方法消耗不同的內存。

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

//測試機器 2.4 GHz Intel Core 2Duo    2GB 667 MHz DDR2   GCC 4.2
- (void)testStringSpeed:(id)sender { NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; [textField setStringValue:@""]; int testi,testnum=10; float c,tm=0.0; for(testi=0;testi<testnum;testi++){ NSDate *beg=[NSDate date]; int i,n=10000000; for(i=0;i<n;i++){ //avg=0.030204 /* { //avg=0.594266 內存基本穩定不變 NSString *t=[[NSString alloc] initWithString:@"abccc"]; [t release]; }*/ /* { //avg=0.026101 內存基本穩定不變 NSString *astring = @"abcc"; }*/ /* { //avg=0.278873 內存基本穩定不變 NSString *astring = [[NSString alloc] init]; astring = @"abcc"; [astring release]; }*/ /* { //avg=2.737541 內存基本穩定不變 char *Cstring = "abcc"; NSString *astring = [[NSString alloc] initWithCString:Cstring]; [astring release]; }*/ /* { //avg=3.619728 內存增長過快 NSString *a=[NSString stringWithString:@"abcc"]; }*/ /* { //太長時間,內存增長過快 NSString *a=[NSString stringWithFormat:@"abcc%d",i]; } */ /* { //avg=0.034632 內存基本穩定不變 char a[]="abcc"; }*/ /* { //18.1555 內存稍有增長 NSString *a=[[NSString alloc] initWithFormat:@"abcc%d",i]; [a release]; }*/ /* { //avg=2.276076 內存基本穩定不變 char a[32]; sprintf(a,"abcc%d",i); }*/ /* { //太長時間,內存增長過快 NSMutableString *a=[[NSMutableString alloc] init]; [a stringByAppendingFormat:@"abcc%d",i]; [a release]; }*/ } c=[[NSDate date] timeIntervalSinceDate:beg]; tm+=c; [textField setStringValue:[NSString stringWithFormat:@"%@\n%d=%f",[textField stringValue],testi+1,c]]; } [textField setStringValue:[NSString stringWithFormat:@"%@\navg=%f",[textField stringValue],(float)tm/testnum]]; [pool release]; }

 

由於stringWithFormat 即耗時又耗內存,所以在cellForRowAtIndexPath 繪制cell 的時消耗大量內存和時間,造成界面滑動不流暢。

 

六、關於 colorWithPatternImage 的內存泄露

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

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

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM