# Block探究 ### 1、Block作为函数参数可以应用到函数式编程 ``` self.prepare.play(@"女人"); - (ViewController *(^)(NSString *))play{ NSLog(@"即将吃喝玩乐"); ViewController *(^block)(NSString *) = ^ViewController *(NSString *fun){ NSLog(@"接下来玩%@,好不好?",fun); return self; }; return block; } - (ViewController *)prepare{ NSLog(@"我们先好好休息一下。😂\n"); return self; } ``` ###2、Block作为函数的返回值可以作为链式编程 ``` [self blockAsFunctionalProgramming]; - (void)blockAsFunctionalProgramming{ [self reprepare:^{ NSLog(@"接下来玩女人,好不好?😊"); }]; } - (void)reprepare:(void(^)(void))replay{ NSLog(@"我们先好好休息一下。😂\n"); replay(); } @end ``` ###3、Block 访问、修改外部变量 * 打开 Terminal.app,编写一段c代码 ``` #include "stdio.h" int main(){ printf("Coming\n"); __block int a = 10; printf("开始->%p %d\n",&a,a); void(^block)(int a) = ^void(int a){ a += 10; printf("中间->%p %d\n",&a,a); }; block(a); printf("结束->%p %d\n",&a,a); return 0; } ``` * 之后用 **gcc** 编译一下。在同层目录下得到一个 **a.out** 的可执行文件。 ``` gcc index.c ``` * 之后用 **clang** 编译成 C++ 文件,可以看到系统底层是如何处理 block 外部的变量、以及如何在 block 里面处理变量的。 ``` clang -rewrite-objc index.c ``` ![clang结果](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WX20180516-235614@2x.png) ###4、Block 经常造成循环引用 * 如果 block 作为函数参数的话,且这个函数是在对象的层级,那么可能会造成循环应用。 self -> func -> block -> self. 此时需要在 block 里面访问 self 的时候将 self 修饰为 __weak