iOS: Foundation和Core Foundation之间的Toll-Free Bridging_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > iOS: Foundation和Core Foundation之间的Toll-Free Bridging

iOS: Foundation和Core Foundation之间的Toll-Free Bridging

 2013/9/30 15:09:37  _Mgen  博客园  我要评论(0)
  • 摘要:目录1.ARC环境下2.非ARC环境下 返回目录1.ARC环境下首先在ARC环境下,如果不需要专门索要对象所有权,可以直接使用__bridge+类型来执行Toll-FreeBridging,因此转换后的对象也不需要进行释放。比如下段代码,不需要专门释放CFStringRef,ARC会释放NSString。他们指向同一个内存数据。//ARC会释放strNSString*str=[[NSStringalloc]initWithCString:"mgen"
  • 标签:Foundation iOS

目录

  • 1. ARC环境下
  • 2. 非ARC环境下

 

返回目录

1. ARC环境下

首先在ARC环境下,如果不需要专门索要对象所有权,可以直接使用__bridge + 类型来执行Toll-Free Bridging,因此转换后的对象也不需要进行释放。

比如下段代码,不需要专门释放CFStringRef,ARC会释放NSString。他们指向同一个内存数据。

//ARC会释放str

NSString *str = [[NSString alloc] initWithCString:"mgen" encoding:NSUTF8StringEncoding];

CFStringRef strRef = (__bridge CFStringRef)str;

 

CFShow(strRef);

 

还有相反方向的,同样,这里ARC不会释放转换后的NSString,原创建方(CFStringRef)有责任去释放对象数据。

//创建的CFStringRef需要释放

CFStringRef strRef = CFStringCreateWithCString(kCFAllocatorDefault, "mgen", kCFStringEncodingASCII);

NSString *str = (__bridge NSString*)strRef;

 

NSLog(@"%@", str);

CFRelease(strRef);

 

如果需要索要对象所有权,对于Foundation到Core Foundation对象的转换,可以使用__bridge_ratained或者CFBridgingRetain函数。

这样转换后,相当于对源对象进行一次retain,因此转换后的Core Foundation对象需手动进行释放。

如下代码:

//输出CFStringRefretain count

void printStrRefRetainCount(CFStringRef ref)

{

    NSLog(@"%ld", CFGetRetainCount(ref));

}

 

//通过__bridge_retained获取从NSString转换retain后的CFStringRef

CFStringRef getCFStringRef()

{

    NSString *str = [[NSString alloc] initWithCString:"mgen" encoding:NSUTF8StringEncoding];

    //返回retained后的CFStringRef

    CFStringRef strRef = (__bridge_retained CFStringRef)str;

    return strRef;

}

 

int main(int argc, const char * argv[])

{

    @autoreleasepool {

        CFStringRef strRef = getCFStringRef();

        printStrRefRetainCount(strRef);

       

        //这里可以使用strRef

       

        //释放

        CFRelease(strRef);

    }

    return 0;

}

 

而对于Core Foundation到Foundation对象的转换,可以使用__bridge_transfer或者CFBridgingRelease函数。转换后的Foundation对象会由ARC来处理。

如下代码:

//输出CFStringRefretain count

void printStrRefRetainCount(CFStringRef ref)

{

    NSLog(@"%ld", CFGetRetainCount(ref));

}

 

//输出NSStringretain count

void printStrRetainCount(NSString *str)

{

    CFStringRef strRef = (__bridge CFStringRef)str;

    NSLog(@"%ld", CFGetRetainCount(strRef));

}

 

//通过__bridge_transfer获取NSString

NSString* getNSString()

{

    CFStringRef strRef = CFStringCreateWithCString(kCFAllocatorDefault, "mgen", kCFStringEncodingUTF8);

    printStrRefRetainCount(strRef);

   

    //移交给ARC处理的NSString

    NSString *str = (__bridge_transfer NSString*)strRef;

    printStrRetainCount(str);

    return str;

}

 

int main(int argc, const char * argv[])

{

    @autoreleasepool {

        NSString *str = getNSString();

        printStrRetainCount(str);

    }

    return 0;

}

 

注意这段代码会输出:

1

2

3

这是由于ARC会在赋值后对变量进行retain。而我们解释的是创建后的CFStringRef不需要进行CFRelease,ARC会自动管理NSString的内存释放。可以通过Xcode中的Product – Analyze来分析代码,不会有任何内存泄露提示的。

 

当然,我们也可以这样做:

NSString *str1 = [[NSString alloc] initWithCString:"mgen" encoding:NSUTF8StringEncoding];

CFStringRef ref1 = (__bridge_retained CFStringRef)str1;

NSString *str2 = (__bridge_transfer NSString*)ref1;

NSLog(@"%@", str2);

哈哈,代码会先在Foundation世界中创建一个NSString,然后把它转换到Core Foundation世界中,最后再转换回来。ARC会最终管理内存释放的。

 

返回目录

2. 非ARC环境下

非ARC环境下很好理解。既然是Toll-Free Bridging,两者可以直接互转,两者指向的也是同一块内存区域。所以Foundation和Core Foundation下的手动内存管理方式是通用的。

如下代码:

void printRetainCount(id obj)

{

    NSLog(@"%lu", (unsigned long)[obj retainCount]);

}

 

int main(int argc, const char * argv[])

{

    @autoreleasepool {

        NSString *str = [[NSString alloc] initWithFormat:@"mgen"];

        printRetainCount(str);

       

        CFStringRef strRef = (CFStringRef)str;

        CFRetain(strRef);

        printRetainCount(str);

       

        [str retain];

        NSLog(@"%ld", (long)CFGetRetainCount(strRef));

       

        NSLog(@"Releasing");

        CFRelease(strRef);

        printRetainCount(str);

        CFRelease(strRef);

        printRetainCount(str);

        CFRelease(strRef);

    }

    return 0;

}

 

输出:

1

2

3

Releasing

2

1

发表评论
用户名: 匿名