iOS Fundation和CoreFoundation的对象转换内存管理权问题

iOS Fundation和CoreFoundation的对象转换

1、对象转换时涉及到内存管理权的问题

背景:Foundation框架和CoreFoundation框架分别是由C语言和OC语言实现的苹果官方库。
就是由于是由不同的语言实现的,在iOS5之后,OC开始支持ARC内存管理。在MRC时代,内存的管理全部要有程序员自己来完成,不涉及内存管理权的移交问题。但是在ARC时代,在Foundation 和 CoreFoundation框架之间的一些对象要相互转换,就必须要考虑内存管理权的问题。两个不同框架生成的对象强制转换时,需要交代清楚到底是让ARC帮我们管理内存还是要我们自己手动管理内存。
苹果提供了3个关键词来解决这一问题,分别是__bridge, __bridge_retain, __bridge_transfer。

2、__bridge关键字

/*
     __bridge 关键字,它的含义是不改变对象管理权的所有者,本来由ARC管理的Foundation对象,转换成Core Foundation 对象后依然由ARC管理;本来由开发者手动管理的Core Foundation对象转换为Foundation 对象后继续由开发者手动管理
     */
    /*ARC 管理的Foundation对象*/
    NSString *s1 = @"111";
    /*转换后,依然有ARC 管理内存*/
    CFStringRef cfStr = (__bridge CFStringRef)s1;
    /*开发者手动管理的 CoreFoundation对象*/
    CFStringRef s2 = CFStringCreateWithCString(NULL, "cf create string", kCFStringEncodingASCII);
    /*转换后仍然需要开发者手动管理释放*/
    NSString *fstring = (__bridge NSString*)s2;

    NSLog(@"s1: %@", s1);
    NSLog(@"cfStr: %@", cfStr);
    NSLog(@"s2: %@", s2);
    NSLog(@"fstring: %@", fstring);
    

如果不做特殊处理s2有内存泄漏的危险:
跑一下代码,做一个内存分析可以发现,Xcode 已经开始抱怨了:
这里是控制台打印:

这里是运行时危险警告:

我们打印下报错地址对应的内容,发现就是 s2:

2、__bridge_transfer关键字

/*
     __bridge_transfer用在将Core Foundation对象转换成Foundation对象时,进行对象管理权的移交。即本来需要由开发者手动管理和释放的Core Foundation 对象在转换成Foundation对象后,交由ARC来管理对象的释放。开发者不需要再关注对象内存释放的问题。
     */
    /*开发者手动管理的Core Foundation对象*/
    CFStringRef cfStr2 = CFStringCreateWithCString(NULL, "cf creat string2", kCFStringEncodingASCII);
    /*转换后改由ARC管理对象的释放,不用担心内存的泄漏*/
    NSString *str2 = (__bridge_transfer NSString *)cfStr2;
    /*等效写法*/
   //NSString *str2 = (NSString *)CFBridgingRelease(cfStr2);

3、__bridge_obtain关键字

   /*
     __bridge_retain 用在将Foundation对象转换成 Core Foundation对象时,进行ARC对象管理权的剥夺。即本来由ARC管理的Foundation对象在转换为Core Foundation对象时,ARC不再继续管理,需要开发者自己手动释放对象所占用的内存,否则会发生内存泄漏。
     */
    /*ARC管理的Foundatioin对象*/
    NSString *s3 = @"string3";
    /*转换后ARC不再继续管理,需要手动释放*/
    CFStringRef cfString3 = (__bridge_retained CFStringRef)s3;
    //另一种写法
    //CFStringRef cfString4 = (CFStringRef)CFBridgingRetain(s3);
原文地址:https://www.cnblogs.com/wjw-blog/p/14469766.html