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 = ^{

      [ self doSomething];
         };
 __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