iOS开发笔记之三十六——开发中内存管理的使用技巧汇总

来源:互联网 发布:js获取所有data属性 编辑:程序博客网 时间:2024/05/23 12:35

       IOS自动有了ARC机制后,以及主流iphone设备不断扩大的内存,让开发者可以不像以前那样严格的考虑内存问题了。但是作为一个开发者,我们还是要尽可能的要写出合理使用内存的程序,尤其在调用某些第三方、开源的API、加载图片等资源文件、处理音视频等场景时,建议大家还是多多注意下。因为ARC下一旦出现内存问题,将更加难以定位与发现,有时即使leak工具也无法发现;此文便是汇总了开发中以及自己在实际的文档搜索中,总结的关于内存管理的一些使用技巧,便于查阅。

1、加载图片的方法:

[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后立即释放,一般用在封面等图比较大的地方。


2、滑动列表的时候,使用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 方法会把隐藏的界面拿来重用,这样节省很多资源。


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;
}

4、循环引用带来的内存泄露。循环引用指两个对象相互引用了对方,从而导致谁也释放不了谁,导致内存泄露。例如声明一个delegate时,一般用assign而不是retain或者strong,因为delegate很容易引起循环引用。出现循环引用的场景还有block语句,例如:

self.myblock = ^{

     [selfdoSomething];
        };
 __block TestCycleRetain *weakSelf =self;
        self.myblock = ^{
 
            [weakSelf doSomething];
        };

以下写法则不会出现循环引用:

//不会循环引用

        __weak TestCycleRetain *weakSelf =self;
        self.myblock = ^{
 
            [weakSelf doSomething];
        };


 //不会循环引用

        __unsafe_unretained TestCycleRetain *weakSelf =self;
        self.myblock = ^{
 
            [weakSelf doSomething];
        };





参考资料:

(1)http://www.chengxuyuans.com/iPhone_IOS/67181.html

(2)http://www.cnbluebox.com/?p=255


0 0