内存管理,ARC

内存管理,ARC,第1张

概述1. 要避免两个对象互相retain的问题; 2.  Core Foundation's memory allocation policy is that you need to release values returned by functions with “Copy” or “Create” or "alloc" in their name;       这是指在corefoundatio

1. 要避免两个对象互相retain的问题;


2.  Core Foundation's memory allocation policy is that you need to release values returned by functions with “copy” or “Create” or "alloc" in their name; 

     这是指在corefoundation.framework中。而Nsstring等是在foundation.framework中。

 

3.不是alloc出来的对象不要执行 autorelease!!!

   alloc方法将分配的内存初始化为0,BOol类型变量被初始化为NO,int为0,float为0.0,指针为nil,所有的基地都属于我们了。

  

4.Cocoa过去没有垃圾回收机制,iPhone现在也没有。所以必须自己通过-retain,-release and -autorelease这些命令使用引用计数(reference counting)技术来管理内存。

   Objective-C的内存管理机制与.Net/Java那种全自动的垃圾回收机制不同,它本质上还是C语言中的手动管理方式,只不过加了一些自动方法。

   为什么iOS中没有GC

    •    GC消耗cpu时间,耗电。
    •    GC执行后,会停掉运行时库;
    ◦    GC执行频率高损失性能:耗内存,影响UI动画处理效果;

5.可以不为应用程序委托AppDelegate提供dealloc方法,因为它永远不会被调用。iPhone OS在应用程序拆卸(tear-down)期间会恢复所有应用程序内存。从技术上讲,视图控制器存在泄漏问题。但是在实践中,这不是问题。

 

6. 在objc 中出现了EXE_BAD_ACCESS,经常是因为访问了被释放了的对象。

    在dealloc时,要把[super dealloc]放到 dealloc的最后调用,否则可能会出现问题,可能是因为释放了NSObject,导致继承该类的其它数据成员没有宿主,导致错误。


7.内存使用经验:
(1)使用尽量少使用或使用小尺寸的UIVIEw层
          对于iPad,一个像素需要4Byte来算,一个层的大小就是 4x1024x768 ~ 3M字节,10个层就是 10x3M = 30M
(2)尽量使用图片pattern,而不是一张大的图片
            与在界面上放一个大底图相比,最佳方案是,设计出一个小的pattern图,然后用这个方案显示成底图。
            UIImage *smallimage = [[UIImage alloc] initWithContentsOffile:path]; 
            backgroundVIEw.backgroundcolor = [UIcolor colorWithPatternImage:smallimage];
             [smallimage release];
(3)使用 NSautoreleasePool 的时候也尽量建议局部使用,比如下面的循环。

         循环中大量生成的自动释放autorelease对象,可以考虑使用autorelease pool封装。代码范例:
    for(UIVIEw *subvIEw in bigVIEw.subvIEws) {  
        // 使用autorelease pool自动释放对象池  
        NSautoreleasePool *pool = [[NSautoreleasePool alloc] init];  
      
        UIImageVIEw *imageVIEw = (UIImageVIEw *)subvIEw;  
          
        // subvIEw处理代码  
        .......  
      
        // 销毁自动释放对象  
        [pool  drain];  
    }
  (4)iOS4.0的multi-tasking特性发布后,程序可以被调入后台运行,苹果工程师的意见是,进入后台运行时,你的应用应该释放掉能释放的对象,尽量保持在16M左右,这样别的程序运行时才不容易把你的应用挤掉。

    (5)生成对象时,使用autorelease; 对象代入时,先autorelease后再retain,Failed Self 的原则;对象在函数中返回时,使用return [[object retain] autorelease];


8.数组和字典的内存管理

    当NSMutableArray被release时,它将自动release所有索引位置上的对象. 应该同样适用于NSArray及其它容器.

    测试NSMutableArray addobject会对添加进的对象发送retain消息;NSMutableDictionary setobject也会对添加的对象发送retain消息;

    当使用AppKit时,Cocoa定期自动创建和销毁自动释放池.通常是在一个事件循环@R_419_6915@这些 *** 作.

    <<objective-c基础教程>>中讲,实际上,在编写iPhone程序时,苹果公司建议你不要在自己的代码中使用autorelease方法,同时还要避免使用那些创建了自动释放对象的便利函数.


9.ios6.0内存警告的兼容处理 vIEwDIDUnload 屏蔽

http://www.cocoachina.com/bbs/simple/?t125949.HTML


判断self.vIEw是否显示在屏幕上

if (self.vIEw.window)

{}  //在iOS程序里面,window是程序视图层次体系的最高层。vIEw要直接或间接加到这个window上才能被看到。即它的window属性值不为nil。


模拟内存警告:

在ios6模拟器中,当前页dIDReceiveMemoryWarning被调用,前一页dIDReceiveMemoryWarning被调用,此时前一页self.vIEw.window为nil,这里如果置前一页的self.vIEw=nil,再返回前一页时,前一页loadvIEw被调用。

在ios5模拟器中,当前dIDReceiveMemoryWarning被调用,前一页的dIDReceiveMemoryWarning、vIEwDIDUnload被调用。再返回前一页,会调用前一页的loadvIEw。

结论:在ios5中,会自动销毁非当前页的vIEwController.vIEw。ios6中,要手动销毁非当前页的vIEwController.vIEw,且不会调用vIEwDIDUnload。只有vIEwController.vIEw被销毁了,vIEwController的loadvIEw,vIEwDIDLoad才会被依次调用。在调用loadVIEw前,self.vIEw会被重新创建,它的内容就是空的了。

所以,基于原ios5的vIEwDIDUnload代码,在ios6中处理代码修改如下:

-(voID)dIDReceiveMemoryWarning
{
    [super dIDReceiveMemoryWarning];
    
    if([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0)
    {
        if ([self.vIEw window] == nil)//非当前视图
        {
            [self vIEwDIDUnload];

           

           /*

              下面self.vIEw = nil;目的是再次进入时能够重新加载,

             此 *** 作不能调用两次,如果调用两次会导致此页面在下面时也会被调用loadvIEw;

             且要销毁所有的子vIEw,在loadvIEw时重新创建,这涉及到保存一些vIEw中的数据,防止丢失。

          */

            self.vIEw = nil;
        }
    }
}


如果不主动执行[self vIEwDIDUnload]或相关函数,则必须要在loadVIEw和vIEwDIDLoad中对一些成员的创建做空建判断。空建即为空是才创建。但[self.vIEw addSubvIEw:xxx];要在空建判断外添加,因为此时self.vIEw内容是空的。


参考 http://www.cnblogs.com/thefeelingofsimple/archive/2012/12/03/2799145.HTML


10.



9.ARC

http://onevcat.com/2012/06/arc-hand-by-hand/

http://www.yifeiyang.net/development-of-the-iphone-simply-1/

  

   在Building Setting中,Apple LLVM compiler 3.1 language 中 “Objectice-C auto Reference Counteting” 项设置是否启用ARC。

   如果只想对某个.m文件不适应ARC,可以只针对该文件加上 -fno-objc-arc 编译FLAGS。而启用arc使用 -fobjc-arc编译选项。

  ARC的一个基本规则即是,只要某个对象被任一strong指针指向,那么它将不会被销毁。如果对象没有被任何strong指针指向,那么就将被销毁。成员对象指针和局部指针默认就是strong的,即ARC中默认的指针类型就是strong

  当对象被销毁后,在ARC机制作用下,所有指向这个对象的@H_890_301@weak指针将被置为@H_890_301@nil。这个特性相当有用,使用ARC以后,不论是还是类型的指针,都不再会指向一个dealloced的对象,不会出现EXCBADACCESS错误,从根源上解决了意外释放导致的crashstrong和retain相似,weak比assign更聪明一些。

    ARC基本规则

retain,release,autorelease,dealloc由编译器自动插入,不能在代码中调用 可以重写dealloc,但不能调用[super dealloc]; 引用关键字

ARC中关于对象的引用参照,主要有下面几关键字。使用strong,weak,autoreleasing限定的变量会被隐式初始化为nil。

__strong 强参照,变量声明缺省都带有__strong关键字。
__weak  弱参照,该类型不影响对象的生命周期,如果对象之前就没有持有者,那么会出现刚创建就被破弃的情况。弱参照还有一个特征,即当参数对象失去所有者之后,变量会被自动付上nil (Zeroing)。
__unsafe_unretained 即MRC的assign

__autoreleasing 该关键字使对像延迟释放。用在函数返回新对象或函数的参数会接管新对象。可以理解为暂只保存对象内存不检查强弱情况,待有指针接管后再检查判断。

- (voID) generateErrorInVariable:(__autoreleasing NSError **)paramError {    ....    *paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary];}
    NSError *error = nil;    [self generateErrorInVariable:&error];    NSLog(@"Error = %@",error);

 
-(Nsstring *)stringTest{    __autoreleasing Nsstring *retStr = [Nsstring alloc] initWithString:@"test"];    return retStr;}

当方法的参数是ID*,或希望方法返回时对象被autoreleased,那么使用该关键字。


伴随ARC的导入,还有一系列函数的定义也被严格定义了,那就是以 init 开头的函数。init 函数作为alloc生成对象的初期化函数,需要按原样直接传递对象给调用段,所以下面的声明是OK的。
-(ID)initWithObject:(ID)obj;

而下面的是NG的。
-(voID)initWithObject;
不过声明为 -(voID) initialize; 是没有问题的。


只能将ARC用在objective-c对象上(也即继承自NSObject的对象),但是如果涉及到较为底层的东西,比如Core Foundation中的malloc()或者free()等,ARC就鞭长莫及了,这时候还是需要自己手动进行内存管理。另外为了确保ARC能正确的工作,有些语法规则也会因为ARC而变得稍微严格一些。

ARC确实可以在适当的地方为代码添加retain或者release,但是这并不意味着你可以完全忘记内存管理,因为你必须在合适的地方把strong指针手动设置到nil,否则app很可能会oom。简单说还是那句话,你必须时刻清醒谁持有了哪些对象,而这些持有者在什么时候应该变为指向nil

使用ARC之后,由于内存问题造成的crash基本就是过去式了,OOM除外。

iOS 5.1 Xcode 4.3版本中,ARC 有效时的属性(@property) 定义的时候,如果不明确指定所有权关键字,那么缺省的就是 strong。但是在 Xcode4.2 中,即使 strong 也要显示指定。


property也可以用来标记,简单地把原来写@H_890_301@retain@H_890_301@assign的地方替换成或者就可以了。


代码示例:

__weak Nsstring *weakname = self.textFIEld.text;


首先,ARC是LLVM3.0编译器的特性,而老的工程默认编译器可能是GCC或者LLVM-GCC,因此第一步就是确认编译器是否正确。在Project设置面板,选择target,在Build Settings中将Compiler for C/C++/Objective-C选为Apple LLVM compiler 3.0或以上。为了确保之后转换的顺利,最好把Treat Warnings as Errors和 Run Static Analyzer都打开,确保在改变编译器后代码依旧没有警告或者内存问题。

Build Settings页面,把Objective-C automatic Reference Counting改成YES(如果找不到的话请看一看搜索栏前面的小标签是不是调成All了..这个选项在Basic里是不出现的),这样工程就将在所有源代码中启用ARC了。

Edit->Refactor下的Convert to Objective-C ARC,点击后会让选择要转换哪几个文件。

Readonly的@property声明要显示声明strong

@property (nonatomic,strong,Readonly) Nsstring *name;


对于强引用的成员vIEw,在出现内存警告时,要在unload中置为nil,

总结

以上是内存溢出为你收集整理的内存管理,ARC全部内容,希望文章能够帮你解决内存管理,ARC所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1068220.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)