关于OC中Block的实现原理,百度可以搜到一堆。但没有一篇文章说明__weak修饰的变量是如何被捕获的为何没影响到原对象的引用计数。以下是对这个丢失的部分的补充。
PS:阅读以下内容之前,应了解Block和weak的实现原理。
1. 首先,main.m有以下代码
typedef void(^Block)();
Block block;
int main(int argc, char * argv[]) {
NSObject *obj = [NSObject new];
NSLog(@"%@",[obj valueForKey:@"retainCount"]);
__weak id weakObj = obj;
block = ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
NSLog(@"weakObj -- %@",[weakObj valueForKey:@"retainCount"]);
});
};
block();
NSLog(@"%@",[obj valueForKey:@"retainCount"]);
sleep(10);
}
2. cd到工程目录后,clang重写
clang -rewrite-objc -fobjc-arc -stdlib=libc++ -mmacosx-version-min=10.7 -fobjc-runtime=macosx-10.7 -Wno-deprecated-declarations main.m
3. 打开main.cpp并观察重写后的block结构体
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__weak id weakObj;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __weak id _weakObj, int flags=0) : weakObj(_weakObj) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
4. 结论
如果你也注意到了__weak id weakObj;
想必已经明了。