问题概要
- _block是否是一个OC对象?
__bridge
相关。
_block是否是一个OC对象?
结论
- 一般来说,block可以看做一个OC对象,但是在编译器底层,block又可以被细分为block对象,独立于OC对象的存在。
分析
- 根据苹果官方文档,明确的指明block是一个OC对象。有兴趣的在文档里面搜索
Working with Blocks
。 - 根据文档Clang 4.0 documentation里面描述的,这里引入一个概念——可保留对象指针(retainable object pointer),这是苹果官方文档Working with Blocks这章里面没有出现过的字眼,这里面是这样描述的:可保留对象指针分为三类: block块指针,OC对象指针,由
__attribute__((NSObject))
标志的指针。 - block一般可以认为是一个OC对象,但是在编译器底层有细分为block对象,独立于OC对象的存在,但是无论怎么描述,可保留对象(一般认为的OC对象)指针都可以受ARC管理。
- 根据苹果官方文档,明确的指明block是一个OC对象。有兴趣的在文档里面搜索
__bridge
相关。(参考文档Clang 4.0 documentation)
__bridge
- 在文档中关于
__bridge
的描述是这样的,可以实现非可保留对象指针以及可保留对象指针之间的转换,转换的两个对象必须一个是可保留对象,另外一个是非可保留对象,不做对象所有权转移,为了方便理解,可保留对象可以认为是一般情况下的OC对象(包括block等),非可保留对象可以认为是Core Foundation里面的对象等。
- 在文档中关于
__bridge_retain
- 文档中对
__bridge_retained
的描述是这样的,__bridge_retained
把可保留对象指针类型转换为非可保留对象指针类型(不可以倒过来),转换前后对象所有权转移(从被转换者转移到转换者)。
(void)bridgeRetain{
CFStringRef fontName = (__bridge CFStringRef)@"PingFangSC-Thin";
CGFloat fontSize = ;
CTFontRef fontRef = CTFontCreateWithName(fontName, fontSize, NULL);
{
id obj = [[NSObject alloc] init];
fontRef = (__bridge CTFontRef)obj;
}
CFRelease(fontRef);
}- 使用
__bridge
的情况
- 一个已经释放掉的对象重复释放,本质上是坏内存访问,无论调这个类的什么方法都会出现坏内存crash,并不特指释放方法,obj的对象所有权没有转移,还是由自身去管理内存,ARC下,可保留对象的内存管理在自动调用release来释放内存。
- 使用
bridge_retain
之后可以运行通过,对象所有权转移到fontRef,所以必须要调用CFRelease函数来管理内存,不然会发生内存泄露。
- 文档中对
__bridge_transform
__bridge_transform
:把非可保留对象指针类型转换为可保留对象指针类型,对象所有权转移,ARC下,自动调用realeas操作。
//示例函数
(void)bridgeTransform{
CFStringRef fontName = (__bridge CFStringRef)@"PingFangSC-Thin";
CGFloat fontSize = ;
CTFontRef fontRef = CTFontCreateWithName(fontName, fontSize, NULL);
UIFont font = (__bridge_transfer UIFont)fontRef;
}使用
__bridge
会出现内存泄露,fontRef的对象所有权没有转移,内存还是要手动释放。
- 使用__bridge_transform的情况,对象所有权转移,内存转移到font来管理,ARC下,可保留对象会自动调用release操作。
目前的项目中的使用很多关于__bridge的用法
- 有以下用法的,感觉先将UIImage转CGImage,在转id再赋给contents,感觉中间的操作是可以去掉的,但是去掉中间的操作发现contents展示是空的。
//这样
animationView.contents = (__bridge id)MQZ_LOAD_QZONE_IMAGE_NO_CACHE("mqz_live_bg.jpg").CGImage;
- 在《ios核心动画高级技巧》这本书中是这样描述的,造成这个现象是由Mac OS的历史原因造成的。它之所以被定义为id类型,是因为在Mac OS系统上,这个属性对CGImage和NSImage类型的值都起作用。如果你试图在iOS平台上将UIImage的值赋给它,只能得到一个空白的图层。
参看资料
- 文档Clang 4.0 documentation,苹果官方文档
- 书籍《ios核心动画高级技巧》