iOS内存使用陷阱


原文地址 http://www.cnblogs.com/zeejun/archive/2012/05/08/2485535.html

在iPhone开发过程中,代码中的内存泄露我们很容易用内存检测工具laeks检测出来,并改之,但有些是因为iOS的缺陷和用法上的错误,leaks检测工具并不能检测出来。以下情况需要注意


一   [UIImage imageNamed:]只适合与UI界面中贴图的读取,较大的资源文件应该尽量避免使用
用UIIMage加载本地图像最常用的是下面三种:
1 用imageNamed方法
[UIImage imageNamed:ImageName];
2  用imageWithContentsFile方法
NSString *thumbnailFile = [NSString stringWithFormat:@"%@/%@.png", [[NSBundle mainBundle] resourcePath], fileName];
UIImage *thumbnail = [UIImage imageWithContentsOfFile:thumbnailFile];
3  用initWithContentsOfFile方法
UIImage *image = [[UIImage alloc]initWithContentsOfFile:filePath]; 
第一种方法为常见方法,利用它可以方便加载资源图片。用imageNamed的方式加载时,会把图像数据根据它的名字缓存在系统内存中,以提高imageNamed方法获得相同图片的性能。即使生成对象被autoReleasePool释放了,这份缓存也不释放,而且没有明确的释放的方法。如果图像很大,并且图像比较多,用这种方式会消耗很大的内存
第二种方法加载图片是不会缓存的,得到对象的时autoRelease
第三种方法要手动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等等。大量的字符操作时,不同的方法消耗不同的内存。
 
   
- (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 imageName:@“bg.png”]];
此方法用图片来设置view的背景颜色,但是在某些设备上会导致内存泄露

猜你喜欢

转载自blog.csdn.net/a_ss_a/article/details/38442913
今日推荐