在简书看到大牛的知识点,发现很多知识点自己一知半解,能做项目但理论不够扎实,默默地去百度总结一下.放到这里和大家交流交流.
如有侵权,告知即删!
01.block的实质是什么?一共有几种block?都是什么情况下生成的?
[传送门][http://www.jianshu.com/p/7fc19fd619be]
<br />
02.为什么在默认情况下无法修改被block捕获的变量? __block都做了什么?
注: 原理解析,通过clang命令将OC转为C++代码来查看一下Block底层实现,clang命令使用方式为终端使用cd定位到main.m文件所在文件夹,然后利用clang -rewrite-objc main.m将OC转为C++,成功后在main.m同目录下会生成一个main.cpp文件
// OC代码如下
void(^myBlock)() = ^{
NSLog(@"global = %d", global);
};
// 转为C++代码如下
void(*myBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, global));
// 将变量类型精简之后C++代码如下,我们发现Block变量实际上就是一个指向结构体__main_block_impl_0的指针,而结构体的第三个元素是局部变量global的值
void(*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, global);
// 我们看一下结构体__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中调用Block的方法转为C++代码如下,实际上是指向结构体的指针myBlock访问其FuncPtr元素,在定义Block时为FuncPtr元素传进去的__main_block_func_0方法
((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
// __main_block_func_0方法代码如下,由此可见NSLog的global正是定义Block时为结构体传进去的局部变量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定义时便是将局部变量的值传给Block变量所指向的结构体,因此在调用Block之前对局部变量进行修改并不会影响Block内部的值,同时内部的值也是不可修改的
注: 原理解析,通过clang命令将OC转为C++代码来查看一下Block底层实现
// OC代码如下
void(^myBlock)() = ^{
NSLog(@"global = %d", global);
};
// 转为C++代码如下
void(*myBlock)() = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_global_0 *)&global, 570425344));
// 将变量类型精简之后C++代码如下,我们发现Block变量实际上就是一个指向结构体__main_block_impl_0的指针,而结构体的第三个元素是局部变量global的指针
void(*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &global, 570425344);
// 由此可知,在局部变量前使用__block修饰,在Block定义时便是将局部变量的指针传给Block变量所指向的结构体,因此在调用Block之前对局部变量进行修改会影响Block内部的值,同时内部的值也是可以修改的
block不可以修改局部变量,可以修改全局变量,静态变量.
<br />
03.模拟一下循环引用的一个情况?block实现界面反向传值如何实现?
循环引用个人理解.
反向传值: 通过给下级页面设置一个带返回值的block属性.可以实现反向传值.