• ios加载图片内存暴涨解决方法,第一中UIKit-setImage,第二种苹果官方demo提供的分片比例裁剪方式,第三种CATiledLayer 详见Demo
  • 定位IOS内存暴增

    2015-04-16 17:37:46
    最近做项目,突然遇到内存暴增。用到了Instruments,定位到了问题所在。先上图 根据内存百分比,一步一步定位到内存增长最大的函数处。

    最近做项目,突然遇到内存暴增。用到了Instruments,定位到了问题所在。先上图



    根据内存百分比,一步一步定位到内存增长最大的函数处。

    展开全文
  •  用for循环处理图片,使用UIGraphicsBeginImageContext对图片进行裁剪缩放操作,内存一直在涨,方法执行结束后内存才会降下来,这种情况会导致内存突然暴涨然后再急速回落 解决方法添加@autoreleasepool自动释放池...

    在开发中遇到使用UIGraphicsBeginImageContext处理图片内存飙涨的问题

           用for循环处理图片,使用UIGraphicsBeginImageContext对图片进行裁剪缩放操作,内存一直在涨,方法执行结束后内存才会降下来,这种情况会导致内存突然暴涨然后再急速回落

    解决方法添加@autoreleasepool自动释放池,及时的释放内部局部变量,避免内存使用峰值过高,及时释放内存的场景。 

    for (int i = 0; i < iCount; ++i)

    {

            @autoreleasepool{

                    UIGraphicsBeginImageContext()

                    UIGraphicsEndImageContext();

            }

    }

    展开全文
  • 在UIImage处理中,时常会使用到drawInRect方法,但是缺点是内存占用过大,且造成内存泄漏无法回收。这一点是因为对象持有,导致不能及时释放的原因。多调用几次这个方法,内存就暴增。所以,目前我采用的方式是,将...

    在UIImage处理中,时常会使用到drawInRect方法,但是缺点是内存占用过大,且造成内存泄漏无法回收。这一点是因为对象持有,导致不能及时释放的原因。
    多调用几次这个方法,内存就暴增。
    所以,目前我采用的方式是,将UIImage对象本地缓存成图片,然后正常释放对象UIGraphicsEndImageContext();
    接着传递出去缓存UIImage的路径进行读取。
    这样内存释放问题就处理了,多次调用这个方法也不会出现内存无法回收的问题。
    尽管网络上查找问题的答案,autoRelease释放池也无法处理。

    展开全文
  • iOS平台的内存使用引用计数的机制,并且引入了半自动释放机制;这种使用上的多样性,导致开发者在内存使用上非常容易出现内存泄漏和内存莫名的增长情况; 本文会介绍iOS平台的内存使用原则与使用陷阱; 深度剖析...
    
    

    iOS平台的内存使用引用计数的机制,并且引入了半自动释放机制;这种使用上的多样性,导致开发者在内存使用上非常容易出现内存泄漏和内存莫名的增长情况; 本文会介绍iOS平台的内存使用原则与使用陷阱; 深度剖析autorelease机制;低内存报警后的处理流程;并结合自身实例介绍内存暴增的问题追查记录以及相关工具的使用情况;

    TAG

    内存暴增,内存泄漏,autorelease;内存报警;

     

    iOS平台内存常见问题

    作为iOS平台的开发者,是否曾经为内存问题而苦恼过?内存莫名的持续增长,程序莫名的crash,难以发现的内存泄漏,这些都是iOS平台内存相关的常见问题;本文将会详细介绍iOS平台的内存管理机制,autorelease机制和内存的使用陷阱,这些将会解决iOS平台内存上的大部分问题,提高了程序的稳定性;

    1 iOS平台内存管理介绍

    iOS平台的内存管理采用引用计数的机制;当创建一个对象时使用alloc或者allWithZone方法时,引用计数就会+1;当释放对象使用release方法时,引用计数就是-1;这就意味着每一个对象都会跟踪有多少其他对象引用它,一旦引用计数为0,该对象的内存就会被释放掉;另外,iOS也提供了一种延时释放的机制AutoRelease,以这种方式申请的内存,开发者无需手动释放,系统会在某一时机释放该内存; 由于iOS平台的这种内存管理的多样性,导致开发者在内存使用上很容易出现内存泄漏或者程序莫名崩溃的情况,本文会详细介绍iOS平台内存的使用规范与技巧以及如何利用工具避免或者发现问题;

    下图是内存从申请到释放的一个完整示例:

     

     

     

    2 iOS平台内存使用原则

    2.1 对象的所有权与销毁

    2.1.1 谁创建,谁释放;

    如果是以alloc,new或者copy,mutableCopy创建的对象,则必须调用release或者autorelease方法释放内存;

    如果没有释放,则导致内存泄漏!

    2.1.2 谁retain,谁释放;

    如果对一个对象发送 retain消息,其引用计数会+1,则使用完必须发送release或者autorelease方法释放内存或恢复引用计数;

    如果没有释放,则导致内存泄漏!

    2.1.3 没创建且没retain,别释放;

    不要释放那些不是自己alloc或者retain的对象,否则程序会crash

    不要释放autorelease的对象,否则程序会crash

    2.2 对象的深拷贝与浅拷贝

    一般来说,复制一个对象包括创建一个新的实例,并以原始对象中的值初始化这个新的实例。复制非指针型实例变量的值很简单,比如布尔,整数和浮点数。复制指 针型实例变量有两种方法。一种方法称为浅拷贝,即将原始对象的指针值复制到副本中。因此,原始对象和副本共享引用数据。另一种方法称为深拷贝,即复制指针 所引用的数据,并将其赋给副本的实例变量。

    2.2.1 深拷贝

    深拷贝的流程是 先创建一个的对象且引用计数为1,并用旧对象的值初始化这个新对象;

    ClassA* objA = [[ClassA alloc] init];

    ClassA* objB = [objA copy];

    objB是一个新对象,引用计数为1,且objB的数据等同objA的数据;

    注意: objB需要释放,否则会引起内存泄漏!

    2.2.2 浅拷贝

    浅拷贝的流程是,无需引入新的对象,把原有对象的引用计数+1即可

    ClassA* objA = [[ClassA alloc] init];

    ClassA* objB = [objA retain];

    注意: objB需要释放,恢复objA的引用计数,否则会引起内存泄漏!

    2.3对象的存取方法

    2.3.1 属性声明和实现

    变量声明的常用属性类型包括readonly,assign,retain和copy;且系统会自动为声明了属性的变量生成set和get函数;

    readonly属性: 只能读,不能写;

    assign属性: 是默认属性,直接赋值,没有任何保留与释放问题;

    retain属性: 会增加原有对象的引用计数并且在赋值前会释放原有对象,然后在进行赋值;

    copy属性:  会复制原有对象,并在赋值前释放原有对象,然后在进行赋值;

    2.3.2 使用属性声明可能带来的隐患

    当一个非指针变量使用retain(或者copy)这个属性时,尽量不要显性的release这个变量;直接给这个变量置空即可;否则容易产生过度释放,导致程序crash; 例如:

    ClassA类的strName是NSString* 类型的变量且声明的属性为retain;

    ClassA.strName = nil;  /* 释放原有对象且对此对象赋值为空 */

    [ClassA.strName release]; /* strName内存可能已经被释放过了,将导致程序crash */

    Assign这个属性一般是非指针变量(布尔类型,整形等)时用这个类型;属于直接赋值型,不需要考虑内存的保留与释放;

    如果一个指针类型的变量使用assign类型的属性,有可能引用已经释放的变量;导致程序crash; 例如:

    ClassB* obj =[[[ClassB alloc] init] autorelease];

    ……

    ClassA.strName = obj; /* strName 指向obj的内存地址*/

    后续在使用ClassA.strName的时候, 因为obj是autorelease的,可能obj的内存已经被回收;导致引用无效内存,程序crash;

    3iOS平台AutoRelease机制

    3.1 自动释放池的常见问题

    大家在开发iOS程序的时候,是否遇到过在列表滑动的情况内存莫名的增长,频繁访问图片的时候内存莫名的增长,频繁的打开和关闭数据库的时候内存莫名的增长…… 这些都是拜iOS的autorelease机制所赐;具体分析如下:

    1: 滑动列表的时候,内存出现莫名的增长,原因可能有如下可能:

    1:没有使用UITableView的reuse机制; 导致每显示一个cell都用autorelease的方式重新alloc一次; 导致cell的内存不断的增加

    2:每个cell会显示一个单独的UIView, 在UIView发生内存泄漏,导致cell的内存不断增长

    2: 频繁访问图片的时候,内存莫名的增长;

    频繁的访问网络图片,导致iOS内部API,会不断的分配autorelease方式的buffer来处理图片的解码与显示; 利用图片cache可以缓解一下此问题;

     

    3: 频繁打开和关闭SQLite,导致内存不断的增长;

    在进行SQLite频繁打开和关闭操作,而且读写的数据buffer较大,那么SQLite在每次打开与关闭的时候,都会利用autorelease的方式分配51K的内存; 如果访问次数很多,内存马上就会顶到几十兆,甚至上百兆! 所以针对频繁的读写数据库且数据buffer较大的情况, 可以设置SQLite的长连接方式;避免频繁的打开和关闭数据库

    3.2 自动释放池的概念

    NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声名为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。

    ClassA *obj1 = [[[ClassA alloc] init] autorelease]; //retain count = 1,把此对象加入autorelease pool中

    NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,对象正式被销毁。如果此时数组中成员的retain count大于1,那么release之后,retain count大于0,此对象依然没有被销毁,内存泄露。

    3.3 自动释放池的作用域与嵌套

    AutoreleasePool是可以嵌套使用的!
    池是被嵌套的,嵌套的结果是个栈,同一线程只有当前栈顶pool实例是可用的:

     

    当短生命周期内,比如一个循环中,会产生大量的临时内存,可以创建一个临时的autorelease pool,这样可以达到快速回收内存的目的;

    3.4 自动施放池的手动创建与自动创建

    3.4.1 需要手动创建自动释放池

    ●如果你正在编写一个不是基于Application Kit的程序,比如命令行工具,则没有对自动释放池的内置支持;你必须自己创建它们。

    ●如果你生成了一个从属线程,则一旦该线程开始执行,你必须立即创建你自己的自动释放池;否则,你将会泄漏对象。

    ●如果你编写了一个循环,其中创建了许多临时对象,你可以在循环内部创建一个自动释放池,以便在下次迭代之前销毁这些对象。这可以帮助减少应用程序的最大内存占用量。

    3.4.2 系统自动创建自动释放池

    Application Kit会在一个事件周期(或事件循环迭代)的开端—比如鼠标按下事件—自动创建一个自动释放池,并且在事件周期的结尾释放它.

    4 iOS平台内存使用陷阱

    4.1 重复释放

    在前文已经提到,不要释放不是自己创建的对象;

    释放自己的autorelease对象,app会crash;

    释放系统的autorelease对象,app会crash;

    4.2 循环引用

     

    循环引用,容易产生野引用,内存无法回收,最终导致内存泄漏!可以通过弱引用的方式来打破循环引用链;所谓的弱引用就是不需要retain,直接赋值的方式,这样的话,可以避免循环引用的问题,但是需要注意的是,避免重复释放的问题;

    5 iOS平台内存报警机制

    由于iOS平台的内存管理机制,不支持虚拟内存,所以在内存不足的情况,不会去Ram上创建虚拟内存;所以一旦出现内存不足的情况,iOS平台会通知所有已经运行的app,不论是前台app还是后台挂起的app,都会收到 memory warning的notice;一旦app收到memory warning的notice,就应该回收占用内存较大的变量;

    5.1 内存报警处理流程

    1: app收到系统发过来的memory warning的notice;

    2: app释放占用较大的内存;

    3: 系统回收此app所创建的autorelease的对象;

    4: app返回到已经打开的页面时,系统重新调用viewdidload方法,view重新加载页面数据;重新显示;

    5.2 内存报警测试方法

    在Simulate上可以模拟低内存报警消息;

    iOS模拟器 -> 硬件 -> 模拟内存警告;

    开发者可以在模拟器上来模拟手机上的低内存报警情况,可以避免由于低内存报警引出的app的莫名crash问题;

    6 iOS平台内存检查工具

    6.1 编译和分析工具Analyze

    iOS的分析工具可以发现编译中的warning,内存泄漏隐患,甚至还可以检查出logic上的问题;所以在自测阶段一定要解决Analyze发现的问题,可以避免出现严重的bug;

    内存泄漏隐患提示

    Potential Leak of an object allocated on line ……

    数据赋值隐患提示

    The left operand of …… is a garbage value;

    对象引用隐患提示

    Reference-Counted object is used after it is released;

     

    以上提示均比较严重,可能会引起严重问题,需要开发者密切关注!

    6.2 内存检测工具

    6.2.1 内存泄漏检测工具—Leak

    Leak工具可以很容易的统计所有内存泄漏的点,而且还可以显示在那个文件,哪行代码有内存泄漏,这样定位问题比较容易,也比较方面;但是Leak在统计内存泄漏的时候会把autorelease方式的内存也统计进来; 所以我们在查找内存泄漏情况的时候,可以autorelease的情况忽略掉;

    Leak工具:

     

     

    通过Leak工具可以很快发现代码中的内存泄漏,通过工具也可以很快找到发生内存泄漏的代码段:

     

    6.2.2 内存猛增检测工具—Allocations

    Allocations工具可以很容易的列出所有分配内存的点,这样我们可以按照分配内存大小来进行排序, 这样可以很容易的发现哪些点分配的内存最多,而且是持续分配,这样我们来针对性的分析这些持续分配较大内存的地方;

     

    此工具会显示出所有申请内存的地方,并统计申请的次数和大小; 从这个列表中可以找出内存申请次数最多且申请内存最大的语句;从而分析出哪些地方使用的内存最多,进而可以优化和改进;

     

    上图是按照申请内存多少来排序的,可以方便的了解哪些代码申请的内存多;

    7 参考资料

    http://www.cocoachina.com/bbs/read.php?tid=15963

    http://developer.apple.com/library/IOs/navigation/

    展开全文
  • 加载webView导致内存泄露的原因是:Html中的js代码会引起内存泄露 解决这个问题的方法是在webViewDidFinishLoad方法中设置如下: ***************  [[NSUserDefaults standardUserDefaults] setInteger:0 for...

    加载webView导致内存泄露的原因是:Html中的js代码会引起内存泄露

    解决这个问题的方法是在webViewDidFinishLoad方法中设置如下:

    ***************

        [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"WebKitCacheModelPreferenceKey"];
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];//自己添加的,原文没有提到。
        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitOfflineWebApplicationCacheEnabled"];//自己添加的,原文没有提到。
        [[NSUserDefaults standardUserDefaults] synchronize];

    ***************

    或者你可以使用wkwebView   

    优点:   加载速度  比UIWebView提升差不多一倍的, 内存使用上面,反而还少了一半。 

    缺点:   WKWebView 不支持缓存 和   NSURLProtocol 拦截了

    我建议如果对缓存不高的页面可以使用,用户体验会提高很多。

    展开全文
  • 使用UIImageJPEGRepresentation内存暴涨,且无法回收。搜索了很多类似的问题,寻找答案。其实原来是对象持有的问题,导致内存无法释放。在拍照,或者从相册选择图片后。把原图保存到本地,然后释放UIImage或NSData...
  • 本例中项目大致流程是先由客户端拍照或者选择图库中的图片进行上传,然后可以从详情页面中浏览所有上传的图片,由于图片是按照相册进行...由此导致需要对图片的加载进行必要的优化,避免程序占用内存过多导致程序崩溃
  • 对于iOS开发者,网络请求类AFNetWorking是再熟悉不过了,对于AFNetWorking的使用我们通常会对通用参数、网址环境切换、网络状态监测、请求错误信息等进行封装。在封装网络请求类时需注意的是需要将请求队列管理者...
  • 内存泄漏指的是程序中已动态分配的堆内存(程序员自己管理的空间)由于某些原因未能释放或无法释放,造成系统内存的浪费,导致程序运行速度变慢甚至系统崩溃。 在 iOS 开发中会遇到的内存泄漏场景可以分为几类: ...
  • 一、1IOS开发中,内存中的对象主要有两类 一类是值类型,比如int、float、struct等基本数据类型。 一类是引用类型,即继承自NSObject类的所有的OC对象。 A、 值类型会被放入栈中, B、 引用类型会被放到堆中 @ ...
  • iOS 内存

    2018-07-21 12:05:31
        观看 Fixing Memory Issues、App Startup Time: Past, Present, and Future 两个视频的总结。 一、Virtual Memory VS Physical Memory     Virtual Memory 是开发者视角的 memory,会分多个 region...
  • ![这个是我的一个开发中的项目的截图]... 一旦运行程序,左边的“memory”就是上面这个走势,等待10多分钟,自己能把自己加到700M,然后成序自己崩掉!...。。
  • 1、对象循环引用 @class ,Strong,weak 2、block循环引用 __weak typeof(self) weakself = self; 3、NSNotification的观察者忘记移除 [[NSNotificationCenter defaultCenter] removeObserver:self]; 4、delegate...
  • 在做浏览本地图片的时候,有大量的本地图片需要加载,初始化的时候就用循环的方式 把所有的图片都加载出来导致内存暴增。该怎么改进。最好有代码~
  • iOS 切换相机出现内存警告,多次拍照,App就被kill 掉了,怎么解决这种内存警告呢?
  • iOS内存优化集合一

    2016-05-03 00:27:02
    视图控制对象通过alloc和init来创建,但是视图控制对象不会在创建的那一刻就马上创建相应的视图,而是等到需要使用的时候才通过调用loadView来创建,这样的做法能提高内存的使用率。比如,当某个标签有很多...
  • 1.先释放。 在 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 方法里面首先调用
1 2 3 4 5 ... 20
收藏数 599
精华内容 239
关键字:

1内存暴涨原因 怎么看ios