前言
iPhone手机用户大多有一个习惯:用完的应用直接Home键。因为大家都知道系统本身会帮我们管理这些应用的存活,这样就给我们iOS 开发带来了挑战!当运行内存吃紧的时候,要及时处理防止应用被杀。
手机运行内存越来越大2G,4G,8G……但是应用也越来越复杂了,所以我们很需要做一些预防措施。
iPhone内存机制是这样的:当应用推到后台是,系统维护一个队列,队列里的应用按优先级区分,等内存警告的时候就按照优先级去kill。所以我们要做的就是收到内存警告的时候去清理应用的缓存释放物理内存,能有效预防被kill。如果收到内存警告不去处理3次可能就被kill了!!!
除了平时养成良好的代码习惯,还要注意一下内容:
1、处理内存警告
- 在什么地方处理
[UIApplationDelegate applicationDidReceiveMeoryWaring]
[UIViewcontroller didReceiveMemoryWaring]
UIApplicationDidReceiveMemoryWoringNotification
- 需要处理什么
清除图片等占用内存多的资源
单例对象不要创建之后一直持有对象数据 警告时释放
隐藏的viewcontroller直接设置self.view=nil
- 示例代码如下:
-(void)didreceivermemoryworing{
[super didreceivememorywaring];
_testdata= nil;
}
2、降低内存峰值
lazyalloction path_one直到使用时才分配 线程安全 不仅分配对象 还有资源文件
Calloc 替代malloc 设置清0标记 只有读写操作的时候才会映射到物理内存并初始化
稍微大一点的图片把imagenamed换成imagewithcontentoffile不缓存
Releasepool 检测主线程分配过大内存或者快速分
imageNamed: 这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象。因此imageNamed的优点是当加载时会缓存图片。所以当图片会频繁的使用时,那么用imageNamed的方法会比较好。
例如:你需要在 一个TableView里的TableViewCell里都加载同样一个图标,那么用imageNamed加载图像效率很高。系统会把那个图标Cache到内存,在TableViewCell里每次利用那个图 像的时候,只会把图片指针指向同一块内存。正是因此使用imageNamed会缓存图片,即将图片的数据放在内存中,iOS的内存非常珍贵并且在内存消耗过大时,会强制释放内存,即会遇到memory warnings。
而在iOS系统里面释放图像的内存是一件比较麻烦的事情,有可能会造成内存泄漏。
例如:当一 个UIView对象的animationImages是一个装有UIImage对象动态数组NSMutableArray,并进行逐帧动画。当使用imageNamed的方式加载图像到一个动态数组NSMutableArray,这将会很有可能造成内存泄露。原因很显然的。
imageWithContentsOfFile:仅加载图片,图像数据不会缓存。因此对于较大的图片以及使用情况较少时,那就可以用该方法,降低内存消耗。
下面列举出两种方法的详细用法:
NSString*path = [[NSBundlemainBundle] pathForResource:@”icon” ofType:@”png”];
UIImage*image = [UIImageimageWithContentsOfFile:path];
以及:
NSString*filePath = [[NSBundlemainBundle] pathForResource:fileName ofType:“png”];
NSData*image = [NSDatadataWithContentsOfFile:filePath];
UIImage*image = [UIImageimageWithData:image];//or = [UIImage imageWithContentsOfFile:filePath];
4、大文件优化内存映射方式
[nsdata datawithcontentsoffile:path]
换成
[nsdata datawithcontentsoffile:path options:nadatareadingmappedifsafe error:&error]
同样是内存映射的方式 是有用的时候才会映射到物理内存 大文件使用
5、设置缓存机制
a、`nacache`设置`totalcostlimit&countlimit `监听内存警告并删除所有的`cache`
b、`Nspurgabledata`适用于大数据低内存的时候自动移除
6、观察log文件
找到lowmemory.log
7、单例模块化
控制单例等全局变量
8、建立清理预防机制
iOS4.0以后系统支持多任务类型,程序按下home键后,程序进入后台运行,如果内存不足被系统关闭或者手动关闭,都不会调用applicationWillTerminate回调函数。
解决方法:可以在程序进入后台时,添加一后台运行通知函数,也就是程序进入后台一段时间内,程序还在运行,并可以响应一些消息。
代码如下:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^(){
//程序在10分钟内未被系统关闭或者强制关闭,则程序会调用此代码块,可以在这里做一些保存或者清理工作
NSLog(@"程序关闭");
}];
}
添加此段代码后,程序进入后台10分钟内会响应 applicationWillTerminate函数,可以在其中添加保存或者清理工作。
这样不仅优化了项目内存电量使用还能有效的后台保活了,赶快做起来吧!