ios 内存使用陷阱
在iphone开发过程中,代码中的内存泄露我们很容易用内存检测工具leaks 检测出来,并一一改之,但有些是因为ios 的缺陷和用法上的错误,leaks 检测工具并不能检测出来,你只会看到大量的内存被使用,最后收到didReceiveMemoryWarning,最终导致程序崩溃。以下是开发过程中遇到的一些问题和网上的一些资料,总结了一下:
一、[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后立即释放,一般用在封面等图比较大的地方。
二、 滑动列表的时候,使用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
详细查看:iPhone/Mac Objective-C内存管理教程和原理剖析(一)基本原理
四、频繁打开和关闭SQLite,导致内存不断的增长
SQLite的数据库本质上来讲就是一个磁盘上的文件,频繁打开和关闭是很耗时和浪费资源的,可以设置SQLite的长连接方式;避免频繁的打开和关闭数据库;
五、在UITableView 的cellForRowAtIndexPath 代理中不要使用 stringWithFormat 方法
定义一个字符串变量有很多方法,最简单的就是 NSString *str = @“abc”, 还有initWithString、stringWithFormat和stringWithCString等等。大量的字符操作时,不同的方法消耗不同的内存。
以下测试代码转自:http://www.cocoachina.com/bbs/read.php?tid-17652-fpage-9.html
//测试机器 2.4 GHz Intel Core 2Duo 2GB 667 MHz DDR2 GCC 4.2- (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 imageNamed:@"bg.png"]];
此方法用图片来设置view的背景颜色,但是某些设备上会导致内存泄露,详细查看:
http://blog.csdn.net/cococoolwhj/article/details/6942981
http://www.cocoaintheshell.com/2011/01/colorwithpatternimage-memory-usage/
转载于:https://www.cnblogs.com/zeejun/archive/2012/05/08/2485535.html
ios 内存使用陷阱相关推荐
- iOS内存暴增问题追查与使用陷阱
iOS平台的内存使用引用计数的机制,并且引入了半自动释放机制:这种使用上的多样性,导致开发者在内存使用上非常容易出现内存泄漏和内存莫名的增长情况: 本文会介绍iOS平台的内存使用原则与使用陷阱: 深度 ...
- 【Bugly干货分享】iOS内存管理:从MRC到ARC实践
本文作者:王拥军 腾讯自选股高级开发工程师 Bugly 技术干货系列内容主要涉及移动开发方向,是由 Bugly 邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创. 对于i ...
- iOS内存管理策略和实践
来源:http://www.baidu.com/link?url=irojqCBbZKsY7b0L2EBPkuEkfJ9MQvUf8kuNWQUXkBLk5b22Jl5rjozKaJS3n78jCnS ...
- iOS内存管理(ARC,MRC)
iOS内存管理方式: ARC Automatic Reference Counting 自动引用计数 MRC Manual Reference Counting 手动引用计数 更改管理方式: 内存管理 ...
- iOS内存管理系列之一:对象所有权与引用计数
原文地址:[转]iOS内存管理系列之一:对象所有权与引用计数作者:anynot 内存管理是iPhone或iPad开发中最为重要的一部分.掌握好了内存管理,开发出的应用就能运行流畅:掌握不好,开发出的东 ...
- iOS内存管理机制解析
软件运行时会分配和使用设备的内存资源,因此,在软件开发的过程中,需要进行内存管理,以保证高效.快速的分配内存,并且在适当的时候释放和回收内存资源. 一.Objective-C内存管理的对象 IOS开发 ...
- Unity手游iOS内存分析和测试
内存是Unity手游的硬伤,如果没有做好内存的相关管理和详细的测试,游戏极有可能出现卡顿.闪退等影响用户体验的现象.在此,笔者为我们介绍了一些Unity手游内存分析和测试过程中比较实用的测试场景案例. ...
- iOS内存分配五大区:
iOS内存分配五大区: 栈区,堆区,静态区(全局区),常量区,代码区 动态数据区一般就是"堆栈",栈是线性结构,堆是链式结构. 本地变量在堆栈中.通过堆栈的基地址和偏移量来访问本地 ...
- 精准 iOS 内存泄露检测工具
MLeaksFinder:精准 iOS 内存泄露检测工具 发表于 2016-02-22 | zepo | 23 Comments 背景 平常我们都会用 Instrument 的 Lea ...
最新文章
- 210328卡式水分开阶段总结
- Warning: Illegal string offset ‘account‘ in 解决方法
- Python算法和数据结构:在二叉树中找到和为sum的所有路径
- 聊一下质量管理体系中的DQE/SQE/PQE/CQE
- C#基础:理解装箱与拆箱
- 【hihocoder 1312】搜索三·启发式搜索(启发式搜索写法)
- wpf window 不执行show 就不能load执行_关于机器学习中的Scikit-Learn,你不知道的10个实用功能...
- Python 进阶 —— 装饰器函数的使用
- mac远程连接linux 服务器桌面by VNC
- TechSmith Camtasia Mac v2021屏幕录制剪辑软件
- delphi 的GetTickCount计时用法缺陷及管制
- PLC-Recorder通过Modbus TCP/Modbus RTU转换器实现RS-485总线设备采集的方法
- 2.70-写出具有如下原型的函数的代码:
- [Matlab] 单次测量的中误差、算数平均值的中误差、加权求最或然值、函数拟合、莫迪图的计算实例
- C程序~一元二次方程求解
- 网易微专业java高级笔记_网易前端微专业------页面架构笔记
- W10电脑U盘插入电脑不显示盘符但是“安全删除硬件并弹出媒体”中却有该U盘
- java实现二维码的生成和解析包含工具类
- 好久没来,深夜来一发
- 我的世界服务器自动被踢怎么可以进去,我的世界中国版服务器中如何解决玩家作弊的简单方法...
热门文章
- C#正则表达式编程(二):Regex类用法
- 虚拟鼠标代替安卓触屏_美术学院18级虚拟空间设计专业数字图像程序基础课程优秀结课成果展示优秀学生王雨禾作品展示...
- 校验输入框的内容不能重复_答应我,用了这个jupyter插件,别再重复造轮子了
- numpy T、transpose()函数、swapaxes()函数
- LIS(Longest Increasing Subsequence)最长上升(不下降)子序列
- 地平线机器人_地平线机器人CEO余凯:基于深度学习的自动驾驶之路
- python requests 10041报错_pythonrequests返回unicode异常消息(或如何设置请求区域设置)...
- 前端如何进行日志驱动开发
- diskgenius 接触“只读“失败_相亲总是失败,这三个步骤你都做了吗?
- java虚拟_Java虚拟机(JVM)工作原理