轉(zhuǎn)自:http://www.cnblogs.com/zeejun/archive/2012/05/08/2485535.html
在iphone開發(fā)過程中即彪,代碼中的內(nèi)存泄露我們很容易用內(nèi)存檢測(cè)工具leaks 檢測(cè)出來,并一一改之活尊,但有些是因?yàn)閕os 的缺陷和用法上的錯(cuò)誤隶校,leaks 檢測(cè)工具并不能檢測(cè)出來,你只會(huì)看到大量的內(nèi)存被使用,最后收到didReceiveMemoryWarning,最終導(dǎo)致程序崩潰挠说。以下是開發(fā)過程中遇到的一些問題和網(wǎng)上的一些資料栗弟,總結(jié)了一下:
一、[UIImage imageNamed:]只適合與UI界面中的貼圖的讀取趟紊,較大的資源文件應(yīng)該盡量避免使用
用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的方式加載時(shí)敛劝,會(huì)把圖像數(shù)據(jù)根據(jù)它的名字緩存在系統(tǒng)內(nèi)存中,以提高imageNamed方法獲得相同圖片的image對(duì)象的性能纷宇。即使生成的對(duì)象被 autoReleasePool釋放了夸盟,這份緩存也不釋放。而且沒有明確的釋放方法像捶。如果圖像比較大上陕,或者圖像比較多,用這種方式會(huì)消耗很大的內(nèi)存拓春。
第二種方法加載的圖片是不會(huì)緩存的释簿。得到的對(duì)象時(shí)autoRelease的,當(dāng)autoReleasePool釋放時(shí)才釋放硼莽。
第三種方法要手動(dòng)release掉庶溶。不系統(tǒng)緩存。release后立即釋放,一般用在封面等圖比較大的地方渐尿。
二醉途、 滑動(dòng)列表的時(shí)候,使用UITableView的reuse機(jī)制
- (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 方法會(huì)把隱藏的界面拿來重用砖茸,這樣節(jié)省很多資源隘擎。
三、要大量創(chuàng)建局部變量的時(shí)候凉夯,可以創(chuàng)建內(nèi)嵌的autorelease pool來及時(shí)釋放內(nèi)存
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"];//產(chǎn)生的對(duì)象是autorelease的货葬。
[loopPool release];
}
[pool release];
return (0);
} // main
詳細(xì)查看:iPhone/Mac Objective-C內(nèi)存管理教程和原理剖析(一)基本原理
四、頻繁打開和關(guān)閉SQLite劲够,導(dǎo)致內(nèi)存不斷的增長
SQLite的數(shù)據(jù)庫本質(zhì)上來講就是一個(gè)磁盤上的文件震桶,頻繁打開和關(guān)閉是很耗時(shí)和浪費(fèi)資源的,可以設(shè)置SQLite的長連接方式征绎;避免頻繁的打開和關(guān)閉數(shù)據(jù)庫蹲姐;
五、在UITableView 的cellForRowAtIndexPath 代理中不要使用 stringWithFormat 方法
定義一個(gè)字符串變量有很多方法人柿,最簡單的就是 NSString *str = @“abc”柴墩, 還有initWithString、stringWithFormat和stringWithCString等等凫岖。大量的字符操作時(shí)江咳,不同的方法消耗不同的內(nèi)存。
以下測(cè)試代碼轉(zhuǎn)自:http://www.cocoachina.com/bbs/read.php?tid-17652-fpage-9.html
//測(cè)試機(jī)器 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