摘要 引用自http://blog.itanbing.com/2015/07/20/block-retain-cycle-problem/
block是2010年WWDC蘋果為Objective-C提供的一個新特性,它為我們開發提供了便利,比如GCD就大量使用了block,用來往執行隊列中添加執行。那么block到底是什么東西呢。其實它就是一個閉包,一個引用自動變量的函數。很多語言也實現自己的閉包,比如C#的lamda表達式。這篇文章將從分析源碼的角度來分析下block到底是什么鬼。
最簡單的block,不持有變量
我們先新建一個源文件:block.c 代碼如下
#include <stdio.h>int main(){
void (^blk)(void) = ^(){printf("This is a block.");};
blk();
return 0;
}
我們使用clang(LLVM編譯器,和GCC類似),通過命令clang -rewrite-objc block.c
,解析block.c這樣我們就會得到對應的cpp文件block.cpp。去除一些影響我們閱讀的代碼。如下:
struct __block_impl {
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int flags=0)
{
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
printf("This is a block.");
}
static struct __main_block_desc_0 {
size_t reserved;
size_t Block_size;
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)};
int main(){
void (*blk)(void) = (void (*)())&__main_block_impl_0((void *)__main_block_func_0 ,&__main_block_desc_0_DATA);
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
return 0;
}