# 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