iOS开发 内存问题

在iphone开发过程中,代码中的内存泄露我们很容易用内存检测工具leaks检测出来,并一一改之,但有些是因为ios的缺陷和用法上的错误,leaks检测工具并不能检测出来,你只会看到大量的内存被使用,最后收到didReceiveMemoryWarning,最终导致程序崩溃。以下是开发过程中遇到的一些问题和网上的一些资料,总结了一下:

一、[UIImageimageNamed:]只适合与UI界面中的贴图的读取,较大的资源文件应该尽量避免使用

用UIImage加载本地图像最常用的是下面三种:

1.用imageNamed方法

[UIImageimageNamed:ImageName];

2.用imageWithContentsOfFile方法

NSString*thumbnailFile=[NSStringstringWithFormat:@"%@/%@.png",[[NSBundlemainBundle]resourcePath],fileName];

UIImage*thumbnail=[UIImageimageWithContentsOfFile:thumbnailFile];

3.用initWithContentsFile方法

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

第一种方法为常见方法,利用它可以方便加载资源图片。用imageNamed的方式加载时,会把图像数据根据它的名字缓存在系统内存中,以提高imageNamed方法获得相同图片的image对象的性能。即使生成的对象被autoReleasePool释放了,这份缓存也不释放。而且没有明确的释放方法。如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存。

第二种方法加载的图片是不会缓存的。得到的对象时autoRelease的,当autoReleasePool释放时才释放。

第三种方法要手动release掉。不系统缓存。release后立即释放,一般用在封面等图比较大的地方。

二、滑动列表的时候,使用UITableView的reuse机制

-(UITableViewCell*)tableView:(UITableView*)tableViewcellForRowAtIndexPath:(NSIndexPath*)indexPath{

staticNSString*CellIdentifier=@"Cell";

UITableViewCell*cell=[tableViewdequeueReusableCellWithIdentifier:CellIdentifier];

if(cell==nil){

cell=[[[UITableViewCellalloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier]autorelease];

}

dequeueReusableCellWithIdentifier方法会把隐藏的界面拿来重用,这样节省很多资源。

三、要大量创建局部变量的时候,可以创建内嵌的autoreleasepool来及时释放内存

intmain(intargc,constchar*argv[])

{

NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];

inti,j;

for(i=0;i<100;i++)

{

NSAutoreleasePool*loopPool=[[NSAutoreleasePoolalloc]init];

for(j=0;j<100000;j++)

[NSStringstringWithFormat:@"1234567890"];//产生的对象是autorelease的。

[loopPoolrelease];

}

[poolrelease];

return(0);

}//main

详细查看:iPhone/MacObjective-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.4GHzIntelCore2Duo2GB667MHzDDR2GCC4.2

-(void)testStringSpeed:(id)sender

{

NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];

[textFieldsetStringValue:@""];

inttesti,testnum=10;

floatc,tm=0.0;

for(testi=0;testi){

NSDate*beg=[NSDatedate];

inti,n=10000000;

for(i=0;i){

//avg=0.030204

}

c=[[NSDatedate]timeIntervalSinceDate:beg];

tm+=c;

[textFieldsetStringValue:[NSStringstringWithFormat:@"%@\n%d=%f",[textFieldstringValue],testi+1,c]];

}

[textFieldsetStringValue:[NSStringstringWithFormat:@"%@\navg=%f",[textFieldstringValue],(float)tm/testnum]];

[poolrelease];

}

由于stringWithFormat即耗时又耗内存,所以在cellForRowAtIndexPath绘制cell的时消耗大量内存和时间,造成界面滑动不流畅。

六、关于colorWithPatternImage的内存泄露

self.view.backgroundColor=[UIColorcolorWithPatternImage:[UIImageimageNamed:@"bg.png"]];

此方法用图片来设置view的背景颜色,但是某些设备上会导致内存泄露,详细查看:

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

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

相关推荐