ARC 概要



三年前,Xcode开发就一直推崇使用ARC内存管理机制, 再往前的岁月里使用的是MRC,那时候retainrelease随处可见,显然MRC已经成为历史,着眼当下:

这里简要罗列了 ARC 的一些知识点概要,

这是一个学习并存在容错的文档翻译。




Transitioning to ARC Release Notes  

 

 1. 首先介绍一个概念:

    现在的 OS X系统 iOS系统 都是没有 垃圾回收 的(GC  Garbage Collection)苹果使用的内存管理的方法是: 应用计数 机制。从原有的MRC 过度到现在更加先进的ARC 制。


 

 2. ARC 使用中感受到最大的好处(如果曾有MRC体验 will more feel):

    对于果农来说,再也不用费尽心思考虑对象的retain release 操作了,解放出庞大的能量,使得更能够专注在有趣的code环节

 


 3. 概要一下ARC

    3.1 ARCMRC都是对遵循着相同的内存管理法则,然而ARC更加优秀,它会在编译的时候(compile time)自动添加一些code来确保对象的必要和生命力。对于其可靠性,(maybe question apple


    3.2 为了确保编译器自动生成正确代码,ARC toll-free bridging(Coare Fundation <-> OC Object)方法做了限制约束;ARC 添加了一些新的对象引用的生命周期修饰符, 和一些属性声明。


    3.3 ARC 起用于系统版本: Xcode4.2 OS X v10.7 iOS 5


    3.4 Xcode 更改工程到ARC模式方法:(choose Edit > Convert to Objective-C ARC);另外对于当个文件,可以使用编译标识来启动或者取消ARCTarget > Build Phases > Compile Sources:弃用ARC 使用 -fobjc-arc 禁用ARC 使用 -fno-objc-arc标识对应文件即可。

 


 4. ARC中一些硬性规则:

    这些规则都是为了让内存管理模式更加可靠,这些规则只在ARC 编译模式下发生作用,既然是硬性的,如果违背就会即刻生成编译时报错。

    4.1 不能实现或调用:retainreleaseretainCount或者autorelease。拓展为不能用@selector(retain),@selector(relase)等。

        也不能直接调用dealloc函数,dealloc 函数在ARC机制下不需要(也不能、会导致编译错误)调用【super dealloc】,它其实是在编译时候自动添加到代码中。对于Core Foundation-syle objects,任然可以使用CFRetainCFRelease


    4.2 不能使用 NSAllocateObject 或者 NSDeallocateObject 使用alloc 穿件对象,运行时会处理好对象的释放。

    

    4.3 不能在C的结构体重使用 对象指针,与其使用结构体,可以使用OC对象来管理数据。


    4.4 id void * 之间存在差异,id 其实是一个对象结构体指针, Objective-C对象和Core Foundation类型之间需要做一些特别定位处理

        NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]];

        [colors addObject:(id)[[UIColor lightGrayColor] CGColor]];


    4.5 不能使用NSAutoreleasePool对象,ARC 提供了@autoreleasepool 块替代,比前者优秀很多。


    4.6 无需再使用 NSZone OC的运行时机制会忽略它们


    4.7 ARC 引入了一些对方法名和属性命名的约束。不能用 new 开头的给一个属性的访问器命名,除非设置了一个特意指定的getter

        // Won't work:

        @property NSString *newTitle;

        // Works:

        @property (getter=theNewTitle) NSString *newTitle;



 5.  ARC 引入的生命时修饰符(Lifetime Qualifiers

    5.1 属性修饰(Property Attributes

        关键字 weak strong

        下面的声明方法同义于: @property(retain) MyClass *myObject;//MRC

        @property(strong) MyClass *myObject;//ARC


        下面的声明方法相似于: @property(assign) MyClass *myObject;//MRC

        @property(weak) MyClass *myObject


        ARC下, stong 是默认的对象属性类型。

 

    5.2 变量修饰(Variable Qualifiers

        __strong 默认修饰,只要有一个强引用存在,对象就始终是‘alive’的。

        __weak 特别标注不用保留引用对象的alive,当改对象不再存在强引用的时候,弱引用会将至置为nil

        __unsafe_unretained,不保留引用对象的alive,对象武强引用是也不置为nil,如果对象释放,指针将悬垂。

        __autoreleasing

 

        使用方式(ClassName * qualifier variableName)如:

            MyClass * __weak myWeakReference;

            MyClass * __unsafe_unretained myUnsafeReference;


        注意当 __weak 变量实在stack 上的时候:

        NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];

        NSLog(@"string: %@", string);

        clang会给出警告:(Assigning retained object to weak variableobject will be released after assignment)

        打印结果是:string: (null)  ???不得解??

    

    5.3 使用修饰符,避免强引用循环(Strong Reference Cycles

        Quote by Linus Torvalds:"Talk is cheap Show me the code":


        As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:


        MyViewController * __block myController = [[MyViewController alloc] init…];

        // ...

        myController.completionHandler =  ^(NSInteger result) {

            [myController dismissViewControllerAnimated:YES completion:nil];

            myController = nil;

        };

        -----------------

        Alternatively, you can use a temporary __weak variable. The following example illustrates a simple implementation:


        MyViewController *myController = [[MyViewController alloc] init…];

        // ...

        MyViewController * __weak weakMyViewController = myController;

        myController.completionHandler =  ^(NSInteger result) {

            [weakMyViewController dismissViewControllerAnimated:YES completion:nil];

        };

        --------------

        For non-trivial cycles, however, you should use:


        MyViewController *myController = [[MyViewController alloc] init…];

        // ...

        MyViewController * __weak weakMyController = myController;

        myController.completionHandler =  ^(NSInteger result) {

            MyViewController *strongMyController = weakMyController;

            if (strongMyController) {

                // ...

                [strongMyController dismissViewControllerAnimated:YES completion:nil];

                // ...

            }

            else {

                // Probably nothing...

            }

        };



 6. ARC 使用心得语法去管理 AutoRelease Pools

    不能直接使用 类:NSAutoreleasePool,可以使用 @autoreleasepool 块语法,它更加强大。 如下

    @autoreleasepool {

        // Code, such as a loop that creates a large number of temporary objects.

    }

    这个简单的结构可以让编译器合理处理引用计数的状态。进入时,自动释放吃就被嵌入(pushed),当正常退出的时候(break,return,goto,fall-through,and so on )自动释放 池就被弹出,不过如果是意外退出的情况,释放池不会弹出(popped)。


 7.  outlets 应该使用weak 但是nib文件中一些来至文件的持有者的高层级的对象需要使用strong windowmenu barscustom controller objects a storyboard scene



 8. Stack 变量将被初始化为nil

    - (void)myMethod {

        NSString *name;

        NSLog(@"name: %@", name);

    }

 

 9. 管理 Toll-Free Bridging

    编译器不会自动管理Core Foundation 对象的内存。需要直接更具框架的内存管理规则 调用CFRetain CFRelease

    如果需要在OC CF 之间做处理 利用宏定义(objc/runtime.h 或者CF类型的宏(定义在NSObject.h)中。

    __bridge  CF OC 之间指针转换   武转换持有关系。

    __bridge_retained / CFBridgingRetain 将一个OC 指针 切换大奥CF指针,并且转移持有关系,需要自己负责释放持有对象关系(使用CFRelease

    __bridge_transfer / CFBridgingRelease 将非OC指针 切换为OC型,并且将持有关系交给ARC

 

 10.dealloc 函数

    因为ARC 不会自动 malloc/free,不管理CF对象、文件描述符 等的生命周期,所以需要自己写一个dealloc函数来释放这些资源。

    完全不用去对一个实例变量进行release,但是需要自己处理一些不遵循ARC的代码,如可能需要插入[self setDelegate:nil]到系统类中。

    ARC中是不允许对dealloc函数调用[super dealloc]的,应为在运行时会自动调用这块代码。



参考文档:ARC Release Notes



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值