iOS 之__block/__weak/__bridge的用法说明

在开发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;
}id __weak obj = strongObj;
}

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

LLVM转换成对应的代码

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

相应的会调用

id obj ;  
objc_initWeak(&obj,strongObj);  
objc_destoryWeak(&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, 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);
}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对象可以在block中被重新赋值,__weak不可以。,https://blog.csdn.net/u014795020/article/details/51088279

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

 

 

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

 

 

 

 

 

 

你可能感兴趣的:(iOS/oc)