__block/__weak/__bridge的用法说明

来源:互联网 发布:android 内存管理源码 编辑:程序博客网 时间:2024/05/23 21:31

在开发iOS应用程序时我们有时会用到Core Foundation对象简称CF,例如Core Graphics、Core Text,并且我们可能需要将CF对象和OC对象进行互相转化,我们知道,ARC环境下编译器不会自动管理CF对象的内存,所以当我们创建了一个CF对象以后就需要我们使用CFRelease将其手动释放,那么CF和OC相互转化的时候该如何管理内存呢?答案就是我们在需要时可以使用__bridge,__bridge_transfer,__bridge_retained,具体介绍和用法如下

1.__bridge:CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化;

NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];CFURLRef ref = (CFURLRef)url;

上面的这段代码在ARC环境下系统会给出错误提示和错误修正,修正后如下:

NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];CFURLRef ref = (__bridge CFURLRef)url;

系统为我们自动添加了__bridge,因为是OC创建的对象并且在转换时没有涉及对象所有权的转换,所以上面的代码不需要加CFRelease

2.__bridge_transfer:常用在讲CF对象转换成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存;(作用同CFBridgingRelease())

 

3.__bridge_retained:(与__bridge_transfer相反)常用在将OC对象转换成CF对象时,将OC对象的所有权交给CF对象来管理;(作用同CFBridgingRetain())

NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];CFURLRef ref = (__bridge_retained CFURLRef)url;CFRelease(ref);
当使用_bridge_retained标识符以后,代表OC要将对象所有权交给CF对象自己来管理,所以我们要在ref使用完成以后用CFRelease将其手动释放.

=========================================

__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。

__weak __typeof(&*self)weakSelf =self; 等同于__weak UIViewController *weakSelf =self;

__weak的实现原理

声明一个__weak对象

{    id __weak obj = strongObj;}

假设这里的strongObj是一个已经声明好了的对象。

LLVM转换成对应的代码

id __attribute__((objc_ownership(none))) obj1 = strongObj;

相应的会调用

id obj ;  objc_initWeak(&obj,strongObj);  objc_destoryWeak(&obj);

objc_initWeak的实现其实是这样的

id objc_initWeak(id *object, id value) {      *object = nil;     return objc_storeWeak(object, value);}

会把传入的object变成0或者nil,然后执行objc_storeWeak函数。

那么objc_destoryWeak函数是干什么的呢?


objc_destoryWeak函数的实现

void objc_destroyWeak(id *object) {      objc_storeWeak(object, nil);}

也是会去调用objc storeWeak函数。objc initWeak和objc destroyWeak函数都会去调用objc storeWeak函数,唯一不同的是调用的入参不同,一个是value,一个是nil。 

那么重点就都落在objc_storeWeak函数上了。

objc storeWeak函数的用途就很明显了。由于weak表也是用Hash table实现的,所以objc storeWeak函数就把第一个传入参数的变量地址注册到weak表中,然后根据第二个入参来决定是否移除。如果第二个参数为0,那么就把__weak变量从weak表中删除记录,并从引用计数表中删除对应的键值记录。 

所以如果__weak引用的原对象如果被释放了,那么对应的__weak对象就会被指为nil。__weak就是通过objc_storeWeak函数这些函数来实现的。




============================================

__block对象可以在block中被重新赋值,__weak不可以。

Block内部能够读取外部局部变量的值。但我们需要改变这个变量的值时,我们需要给它附加上__block修饰符。

__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。




0 0