iOS的一些内存注意点

ios 图片加载方式,内存控制,尽量避免使用imageNamed,使用ARC也需要 

1.为什么尽量避免使用imageNamed?

使用这种方式生成的对象被autorelease之后,图片依然存在于内存,并不会及时回收,并且没有明确的释放方法。如果图像比较大,或者图像比较多,用这种方式会消耗很大的内存。

这是为什么?如果对于大量同一图片的复,使用这个方法可行。以这种方式加载的图片会缓存一份在内存中,以后如果发现有同名的图片,则不会再次加载。缺点是这份缓存无法预知释放时间与条件。

2.最好使用方式:imageWithContentsOfFile,根据文件路径加载图片。这种方式加载的图片不会缓存在内存中,当对象被释放之后,图片也会被释放。

#define recourcesPath [[NSBundle mainBundle] resourcePath]

NSString * imageFile

= [[NSString alloc] initWithFormat:@"%@/%@",recourcesPath, filename];

UIImage

* tempImage = nil;

tempImage = [[UIImage alloc] initWithContentsOfFile:imageFile];

[imageFile release];

imageFile = nil;

这样得到的图片tempImage,并不是autorelease,这可以手动释放,释放的时候已将图片从内存中清除,可控内存是它的优点。

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

四、频繁打开和关闭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

NSDate *beg=[NSDate date];

int i,n=10000000;

for(i=0;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的背景颜色,但是某些设备上会导致内存泄露


你可能感兴趣的:(iOS)