__bride、__bride_transfer和__bride
2019-08-08 本文已影响0人
祥子_HelloWorld
在上一篇里讲到内存泄漏的检测,有一处内存泄露是由于CoreFoundation创建的对象没有释放掉,在开发中Foundation和CoreFoundation框架里的对象需要转换才能用。
一、ARC和Foundation、CoreFoundation
和它一样的还有__bride_transfer和__bride_retain,那么他们之间有什么关系和区别呢?在讲这个之前我们先看一下ARC和Foundation、CoreFoundation框架之间的关系:
二、__bride、__bride_transfer和__bride_retain的区别和作用
所以,在非ARC下两者互转都是需要手动管理内存的,我们重点关注的是在ARC下转换注意的地方。那么下面就是在ARC下,__bride、__bride_transfer和__bride_retain的区别和作用:
三、用法实例
接上一篇的一个内存泄露的例子,下面代码中C语言创建的两个对象没有释放:
+ (NSString *)createUUID
{
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStrRef = CFUUIDCreateString(NULL, uuidRef);
NSString *uuidStr = [NSString stringWithFormat:@"%@",uuidStrRef];
return uuidStr;
}
在上一篇中我们给出的解决办法,也是最直观的办法是手动释放对象的内存:
+ (NSString *)createUUID
{
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStrRef = CFUUIDCreateString(NULL, uuidRef);
NSString *uuidStr = [NSString stringWithFormat:@"%@",uuidStrRef];
CFRelease(uuidRef);
CFRelease(uuidStrRef);
return uuidStr;
}
其实在上面提到的__bride_transfer和__bride_retain也可以解决类似的内存管理的问题,比如下面这种改法:
+ (NSString *)createUUID
{
CFUUIDRef uuidRef = CFUUIDCreate(NULL);
CFStringRef uuidStrRef = CFUUIDCreateString(NULL, uuidRef);
NSString *uuidStr = (__bridge_transfer NSString *)uuidStrRef;
return uuidStr;
}
__bridge_transfer用在将CoreFoundation对象转换成Foundation对象,用于进行内存管理权移交,手动变自动,所以创建的对象交给了ARC去管理,就不用手动释放了。
四、三种示例
/* ARC管理的Foundation对象 */
NSString *s1 = @"string";
//转换后依然由ARC管理释放
CFStringRef cfstring = (__bridge CFStringRef)s1;
//开发者手动管理的CoreFoundation对象,需要手动释放
CFStringRef s2 = CFStringCreateWithCString(NULL, "string", kCFStringEncodingASCII);
//转换后依然需要开发者手动管理释放
NSString *fstring = (__bridge NSString*)s2;
//手动释放CFRelease(s2);
/* 转换后改由ARC管理对象的释放,不用担心内存泄露 */
NSString *fstring1 = (__bridge_transfer NSString*)s2;
//等效于
//NSString *fstring1 = (NSString*)CFBridgingRelease(s2);
/* 转换后ARC不再继续管理,需要手动释放 */
CFStringRef cfstring1 = (__bridge_retained CFStringRef)s1;
//等效于
//CFStringRef cfstring1 = (CFStringRef)CFBridgingRetain(s1);
还有一篇iOS __bridge那些事讲的也很详细,可以参考一下。