從最簡單的block開始開起蕴茴,有一些淺顯的心得如下:
在main.m文件生成如下代碼:
int main(int argc, const char * argv[]) {
void(^blk)(void) = ^{NSLog(@"Block");};
blk();
}
通過命令行翻譯(clang -rewrite-objc main.m)
刪除不必要代碼得到如下的c++文件
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) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_c8_pr2fhjtd5kz0_53s61zxc_400000gn_T_main_c32327_mi_0);
}
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(int argc, const char * argv[]) {
void(*blk)(void) = ((void (*)())&__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA));
((void (*)(__block_impl *))((__block_impl *)blk)->FuncPtr)((__block_impl *)blk);
((blk)->FuncPtr)(blk);
return 0;
}
在block上的代碼 翻譯后 主要是變成了靜態(tài)函數__main_block_func_0
從生成的代碼上觀察主要變成了封裝的若干結構體
從上到下依次觀察結構體聚磺,
__block_impl結構體是系統(tǒng)默認規(guī)定的結構體,并不是該代碼翻譯過來的結構體房匆,結構體內部有isa指針(通常通俗的理解,擁有isa指針都會是一個對象乒裆,也就是說block會成為一個對象的可能碗誉,但這里不深究) ,觀察最后一個變量
void FuncPtr; void 類似于oc中的id類型 (萬能指針) 但從系統(tǒng)給出的變量名字可以看出是一個函數指針 也就是說oc中的block轉換成多個結構體進行封裝的函數指針
也就是說我們可以仿照轉換的代碼進行構造block
按照生成的代碼風格進行 仿造后 得到如下代碼:
struct __block_impl {
void *FuncPtr;
};
struct __main_block_impl_0 {
struct __block_impl impl;
__main_block_impl_0(void *fp) {
impl.FuncPtr = fp;
}
};
static void __main_block_func_0() {
NSLog(@"Block");
}
int main(int argc, const char * argv[]) {
struct __main_block_impl_0 s = __main_block_impl_0((void *)__main_block_func_0);
void(*blk)(void) = ((void (*)())&s);
((void (*)())((__block_impl *)blk)->FuncPtr)();
return 0;
}
該代碼是在原有代碼的基礎上 刪除了多余結構體變量 盡量做到最簡化實現瞒滴,在main函數上 是保持了翻譯后的代碼風格曲梗,看上去有些亂,在此基礎上寫了一個更易理解的調用形式如下:
int main(int argc, const char * argv[]) {
struct __main_block_impl_0 s = __main_block_impl_0((void *)__main_block_func_0);
void(*blk)(void) = (void (*)())s.impl.FuncPtr;
blk();
return 0;
}
從上述描述上看妓忍,起碼最簡單的block 虏两,最終也會形成一種函數,只不過是通過函數指針的形式進行調用世剖,綜上定罢,可以通俗的理解為
block=函數+若干結構體封裝(內部有函數指針變量)