在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/