在簡(jiǎn)書(shū)看到大牛的知識(shí)點(diǎn),發(fā)現(xiàn)很多知識(shí)點(diǎn)自己一知半解,能做項(xiàng)目但理論不夠扎實(shí),默默地去百度總結(jié)一下.放到這里和大家交流交流.
如有侵權(quán),告知即刪!
01.block的實(shí)質(zhì)是什么力细?一共有幾種block环凿?都是什么情況下生成的?
[傳送門(mén)][http://www.reibang.com/p/7fc19fd619be]
<br />
02.為什么在默認(rèn)情況下無(wú)法修改被block捕獲的變量淋淀? __block都做了什么?
注: 原理解析,通過(guò)clang命令將OC轉(zhuǎn)為C++代碼來(lái)查看一下Block底層實(shí)現(xiàn),clang命令使用方式為終端使用cd定位到main.m文件所在文件夾,然后利用clang -rewrite-objc main.m將OC轉(zhuǎn)為C++,成功后在main.m同目錄下會(huì)生成一個(gè)main.cpp文件
// OC代碼如下
void(^myBlock)() = ^{
NSLog(@"global = %d", global);
};
// 轉(zhuǎn)為C++代碼如下
void(*myBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, global));
// 將變量類型精簡(jiǎn)之后C++代碼如下,我們發(fā)現(xiàn)Block變量實(shí)際上就是一個(gè)指向結(jié)構(gòu)體__main_block_impl_0的指針,而結(jié)構(gòu)體的第三個(gè)元素是局部變量global的值
void(*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, global);
// 我們看一下結(jié)構(gòu)體__main_block_impl_0的代碼
struct __main_block_impl_0 {
struct __block_impl impl;
struct __main_block_desc_0* Desc;
int global;
__main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _global, int flags=0) : global(_global) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
// 在OC中調(diào)用Block的方法轉(zhuǎn)為C++代碼如下,實(shí)際上是指向結(jié)構(gòu)體的指針myBlock訪問(wèn)其FuncPtr元素,在定義Block時(shí)為FuncPtr元素傳進(jìn)去的__main_block_func_0方法
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
// __main_block_func_0方法代碼如下,由此可見(jiàn)NSLog的global正是定義Block時(shí)為結(jié)構(gòu)體傳進(jìn)去的局部變量global的值
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
int global = __cself->global; // bound by copy
NSLog((NSString *)&__NSConstantStringImpl__var_folders_6y_vkd9wnv13pz6lc_h8phss0jw0000gn_T_main_d5d9eb_mi_0, global);
}
// 由此可知,在Block定義時(shí)便是將局部變量的值傳給Block變量所指向的結(jié)構(gòu)體,因此在調(diào)用Block之前對(duì)局部變量進(jìn)行修改并不會(huì)影響B(tài)lock內(nèi)部的值,同時(shí)內(nèi)部的值也是不可修改的
注: 原理解析,通過(guò)clang命令將OC轉(zhuǎn)為C++代碼來(lái)查看一下Block底層實(shí)現(xiàn)
// OC代碼如下
void(^myBlock)() = ^{
NSLog(@"global = %d", global);
};
// 轉(zhuǎn)為C++代碼如下
void(*myBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_global_0 *)&global, 570425344));
// 將變量類型精簡(jiǎn)之后C++代碼如下,我們發(fā)現(xiàn)Block變量實(shí)際上就是一個(gè)指向結(jié)構(gòu)體__main_block_impl_0的指針,而結(jié)構(gòu)體的第三個(gè)元素是局部變量global的指針
void(*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &global, 570425344);
// 由此可知,在局部變量前使用__block修飾,在Block定義時(shí)便是將局部變量的指針傳給Block變量所指向的結(jié)構(gòu)體,因此在調(diào)用Block之前對(duì)局部變量進(jìn)行修改會(huì)影響B(tài)lock內(nèi)部的值,同時(shí)內(nèi)部的值也是可以修改的
block不可以修改局部變量,可以修改全局變量,靜態(tài)變量.
<br />
03.模擬一下循環(huán)引用的一個(gè)情況?block實(shí)現(xiàn)界面反向傳值如何實(shí)現(xiàn)?
循環(huán)引用個(gè)人理解.
反向傳值: 通過(guò)給下級(jí)頁(yè)面設(shè)置一個(gè)帶返回值的block屬性.可以實(shí)現(xiàn)反向傳值.