概述
CFBridgingRetain和CFBridgingRelease
在Core Foundation框架和Foundation框架中有大量的可互换使用的数据类型。
这意味着你可以使用相同的数据类型,作为Core Foundation框架方法调用或Objective-C消息的参数或接收者。
这种在Core Foundation框架和Foundation框架之间交换使用数据类型的技术就叫"免费桥" (Toll-Free Bridging)。
一般我们使用CFBridgingRetain
完成对NSObject对象转为CF实例,使用CFBridgingRelease
完成CF实例转NSObject对象
CFBridgingRelease
会导致CF实例引用计数-1,例如下面例子
void RunLoopSourcePerformRoutine (void *info)
{
NSLog(@"RunLoopSourcePerformRoutine %p",info);
RunLoopSource*
obj = (RunLoopSource*)CFBridgingRelease(info);
NSLog(@"RunLoopSourcePerformRoutine %@",[obj valueForKey:@"retainCount"]);
[obj sourceFired];
obj = nil;
}
RunLoopSource* obj = (RunLoopSource*)CFBridgingRelease(info);
RunLoopSource* obj = (__bridge RunLoopSource*)(info);
在Runloop的自定义添加Source0回调中,返回的info可直接转换为RunLoopSource
,但如果使用CFBridgingRelease
,相当于把引用计数-1,会导致对象提前释放。所以在使用这个函数的同时,需要判断来源来自哪里,不要盲目就CFBridgingRelease
#if __has_feature(objc_arc)
// After using a CFBridgingRetain on an NSObject, the caller must take responsibility for calling CFRelease at an appropriate time.
NS_INLINE CF_RETURNS_RETAINED CFTypeRef _Nullable CFBridgingRetain(id _Nullable X) {
return (__bridge_retained CFTypeRef)X;
}
NS_INLINE id _Nullable CFBridgingRelease(CFTypeRef CF_CONSUMED _Nullable X) {
return (__bridge_transfer id)X;
}
#else
// This function is intended for use while converting to ARC mode only.
NS_INLINE CF_RETURNS_RETAINED CFTypeRef _Nullable CFBridgingRetain(id _Nullable X) {
return X ? CFRetain((CFTypeRef)X) : NULL;
}
// This function is intended for use while converting to ARC mode only.
NS_INLINE id _Nullable CFBridgingRelease(CFTypeRef CF_CONSUMED _Nullable X) {
return [(id)CFMakeCollectable(X) autorelease];
}
#endif
显示转换id和void*
对于__bridge_transfer
和__bridge_retained
,用于显示转换id和Void*
在ARC无效时,以下代码将id变量强制转换为void*变量并不会出问题
/* ARC无效 */
id obj = [[NSObject alloc] init];
void *p = obj;
更进一步,将void*变量赋值给id变量中,调用其实例方法,运行时也不会有问题
/* ARC无效 */
id o = p;
[o release];
但是在ARC有效时,会出现如下错误
Implicit conversion of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast
如果只想单纯的转换,不涉及变量持有关系,可以这样
id obj = [[NSObject alloc] init];
void *p = (__bridge void*)obj;
id o = (__bridge id)p;
这样void*和id类型就能够互相转换。
_bridge转换中还有两种转换,__bridge_transfer
和__bridge_retained
__bridge_retained
转换可使要转换赋值的变量也持有所赋值的对象
id obj = [[NSObject alloc] init];
void *p = (__bridge_retained void*)obj;
上面这段代码相当于ARC无效时的
id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain];
__bridge_transfer
提供与此相反的动作,被转换的变量所持有的对象在该变量被赋值给转换目标变量后随之释放
//p为void*类型
id obj = (__bridge_transfer id)p;
ARC无效时,表述如下
/* ARC无效 */
id obj = (id)p;
[obj retain];
[(id)p release];
最后
以上就是合适棒球为你收集整理的OC笔记-CFBridgingRetain和CFBridgingReleaseCFBridgingRetain和CFBridgingRelease显示转换id和void*的全部内容,希望文章能够帮你解决OC笔记-CFBridgingRetain和CFBridgingReleaseCFBridgingRetain和CFBridgingRelease显示转换id和void*所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复