ARC内存管理下的注意事项

本文深入探讨ARC环境下引发内存泄漏的两大常见原因:Block使用不当导致的循环引用及CoreFoundation对象的手动内存管理。通过实例解析如何避免Block引起的循环引用,并详解CF对象与Objective-C对象转换时的内存管理技巧。
摘要由CSDN通过智能技术生成

ARC不是万能的,那ARC下哪些疏漏会引发内存泄漏呢?

(1)Block使用不当造成的循环引用:

    ARC下,copy到堆上的block,会强引用进入到该block中的外部变量.这很容易导致循环引用的问题.

    比方说:

    一个VC(这里指一个controller)中有一个属性为model.VC强引用了它.

    VC --> model

    这个model呢,里面有一个copy属性的block,该block赋值如下如下.model.demo = ^{

    ......

    };

    如果这个......没有传VC进来,还好,不会强引用VC,如果是下面的情况:

    model.demo = ^{

    ......

    [test getValue:self];

    };

    那,直接导致的后果就是,这个model强引用了这个VC.

    model --> VC

    这就造成了一个循环.即使这个VC被pop掉了,垃圾回收机制也无法释放这个VC了,因为,它检测到了这个VC被model强引用了.

    所以,在ARC下面使用block,无论怎样,你都需要注意这几点:

    1. 外部对象进入block,请使用__weak修饰后再进入到block中

    2. 不要在block中初始化对象,请在block的外面初始化对象后再进入到block中去

    3. 无论该block是不是copy的,请都当做copy的block来处理

    4. 传入到堆区block中的对象会被强引用

 

(2)底层Core Foundation对象的内存管理必须手工进行,如:

    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT",fontSize,NULL);

        //引用计数+1

        CFRetain(fontRef);

        //引用计数-1

        CFRelease(fontRef);

        Core Foundation对象和Objective-c对象的转化:__bridge关键字

        __bridge:只做类型转换,不修改相关对象的引用计数,原来的CoreFoundation对象在不用时,需要调用CFRElease

        __bridge_retained:类型转换后,将相关对象的引用计数+1,原来的Core Foundation对象在不用时,需要调用CFRelease

        __bridge_transfer:类型转换后,将该对象的引用计数交给ARC管理,Core Foundation对象在不用时,不再需要CFRelease

        详情:

        在开发iOS应用程序时我们有时会用到Core Foundation对象简称CF,例如Core Graphics、Core Text,并且我们可能需要将CF对象和OC对象进行互相转化,我们知道,ARC环境下编译器不会自动管理CF对象的内存,所以当我们创建了一个CF对象以后就需要我们使用CFRelease将其手动释放,那么CF和OC相互转化的时候该如何管理内存呢?答案就是我们在需要时可以使用__bridge,__bridge_transfer,__bridge_retained,具体介绍和用法如下

        1.__bridge:CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化;

        NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];

        CFURLRef ref = (CFURLRef)url;

        上面的这段代码在ARC环境下系统会给出错误提示和错误修正,修正后如下:

        NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];

        CFURLRef ref = (__bridge CFURLRef)url;

        系统为我们自动添加了__bridge,因为是OC创建的对象并且在转换时没有涉及对象所有权的转换,所以上面的代码不需要加CFRelease

 

        2.__bridge_transfer:常用在讲CF对象转换成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存;(作用同CFBridgingRelease())

 

        3.__bridge_retained:(与__bridge_transfer相反)常用在将OC对象转换成CF对象时,将OC对象的所有权交给CF对象来管理;(作用同CFBridgingRetain())

        NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];

        CFURLRef ref = (__bridge_retained CFURLRef)url;

        CFRelease(ref);

        当使用_bridge_retained标识符以后,代表OC要将对象所有权交给CF对象自己来管理,所以我们要在ref使用完成以后用CFRelease将其手动释放.

        CFStringRef cfString= CFURLCreateStringByAddingPercentEscapes(

        NULL,

        (__bridge CFStringRef)text,

        NULL,

        CFSTR("!*’();:@&=+$,/?%#[]"), CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));

        NSString *ocString = (__bridge_transfer CFStringRef)cfString;

        此时OC即获得了对象的所有权,ARC负责自动释放该对象,如果我们在结尾加上CFRelease(cfString)纯属画蛇添足,虽不会崩溃,但是控制台会打印出该对象被free了两次

 

有关ARC与MRC的比较好的文章:https://hit-alibaba.github.io/interview/iOS/ObjC-Basic/MM.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值