• 【转】内存管理的一些经验和实践方法



    我一直惊叹iOS和Objective-C内存处理能力,例如iPad版本的iWork,Pages应用就是一个内存处理技术应用的鬼斧神工之作。想想256M内存的iPad,可以带来如此的华丽的界面同时获得如此流畅的用户体验,真是不简单。原因就是iOS一直提倡开发者在有限硬件资源内写出最优化的代码,使用CPU最少,占用内存最小。

    (以下代码适用于iOS SDK 4.1, 由于新SDK 4.2对内存使用有新改动,所以可能有不同。。。)
    1. 尽量少的UIView层
    通常我们喜欢把很多控件层(UILabel,UIButton,UIView等)一起放到一个大的UIView容器来显示我们的内容,这个方法一般是可以的,但是如果要经常重新刷新内容的大区域界面,多数发生在iPad的应用中,这个方法会带来过多的内存使用和动画的延迟(比较卡),例如,scrollview的动画比较卡,又或者,经常收到内存警告。其中一个重要原因是每个控件,特别是透明底的,会多次重新绘制(drawRect)过多。其解决办法是,尽量将几个控件合并到一个层上来显示,这样系统会减少系统调用drawRect,从而带来性能上的提升。

    很简单的一个例子,就是iNotes提供手写功能,用户可以在iPad屏幕上写出不同的笔画,开始的设计是,用户每写一划,iNotes就会生成一个新的透明底UIView来保持这个笔画,用户写了10笔,系统就生产了10个UIView,每个view的大小都是整个屏幕的,以便用户的undo操作。这个方案带来严重的内存问题,因为系统将每个层都保持一个bitmap图,一个像素需要4bit来算,一个层的大小就是 4x1024x768 ~ 3M, 10个层就是 10x3M = 30M,很明显,iPad很快爆出内存警告。

    这个例子最后的方案是,所有笔画都画在同一个层,iNotes可以保存笔画的点进行undo操作。这样的方案就是无论用户画多少笔画,界面重画需要的资源都是一样的。

    2. 显示最佳尺寸的图片
    很多程序员比较懒,网络上拿下来的图片,直接就用UIImageView将其显示给用户,这样的后果就是,程序需要一直保存着大尺寸的图片到内存。解决办法应该是先将图片缩小到需要显示的尺寸,释放大尺寸图片的内存,然后再显示到界面给用户。

    3. 尽量使用图片pattern,而不是一张大的图片
    例如,很多界面设计者喜欢在界面上放一个大底图,但这个底图是老是占用着内存的,最佳方案是,设计出一个小的pattern图,然后用这个方案显示成底图。

    C代码 复制代码 收藏代码
    1. UIImage *smallImage = [[UIImage alloc] initWithContentsOfFile:path];     
    2.      
    3. backgroundView.backgroundColor = [UIColor colorWithPatternImage:smallImage];     
    4.      
    5. [smallImage release];    


    4. 使用完资源后,立即释放
    一般objective-c的习惯是,用完的资源要立即释放,因为明白什么时候用完某个资源的是程序员你自己。
    例如,我们要读较大的图片,把它缩小后,显示到界面去。当大图片使用完成后,应该立即释放。代码如下:

    C代码 复制代码 收藏代码
    1. UIImage *fullscreenImage = [[UIImage alloc] initWithContentOfFile:path];     
    2. UIImage *smallImage = [self resizeImage:fullscreenImage];     
    3.      
    4. [fullscreenImage release];     
    5.      
    6. imageView.image = smallImage;     
    7.      
    8. ......   


    5. 循环中大量生成的自动释放autorelease对象,可以考虑使用autorelease pool封装
    代码范例:

    C代码 复制代码 收藏代码
    1. for(UIView *subview in bigView.subviews) {     
    2.     // 使用autorelease pool自动释放对象池     
    3.     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];     
    4.      
    5.     UIImageView *imageView = (UIImageView *)subview;     
    6.          
    7.     // subview处理代码     
    8.     .......     
    9.      
    10.     // 销毁自动释放对象     
    11.     [pool  drain];     
    12. }    


    自动释放对象池把每个循环内生成的临时对象使用完后立即释放

    以上的意见是本人多年来编写iPad/iPhone程序的经验,另外iOS4.0的multi-tasking特性发布后,程序可以被调入后台运行,苹果工程师的意见是,进入后台运行时,你的应用应该释放掉能释放的对象,尽量保持在16M左右,这样别的程序运行时才不容易把你的应用挤掉。

  • 相关阅读:
    HTTP POST GET 本质区别详解
    追求代码质量: 监视圈复杂度
    【置顶】用Eclipse开发Android应用程序索引贴
    Android访问WCF服务(上篇)服务端开发
    做一个T型技术人才
    创新创业大讲堂第一讲
    河海嵌芯FTP服务器开通运行
    嵌芯队团队邮箱以及邮件订阅功能使用说明
    基于视频的公共事件检测分析系统
    感知交通基于视频的交通流特征参数监测及交通综合信息服务系统
  • 原文地址:https://www.cnblogs.com/ygm900/p/2880704.html
Copyright © 2020-2023  润新知