Block探究

知识点:

  • Block初探
  • Block循环引用
  • Block底层原理
  • Block应用进阶

 

一. Block初探

Block的分类

 1  // mian thread [block copy]
 2     int a = 10; // 捕获外部变量
 3     void(^block)(void) = ^{
 4         
 5         NSLog(@"hello block %d",a);
 6     }; // 匿名函数
 7     
 8     block();
 9     
10     NSLog(@"%@",block); // 万物皆对象,block也是对象 RAC: 万物皆signal
11     
12     // block 分类
13     // NSGlobalBlock : 静态区 (没有int a)
14     // NSMallocBlock : 堆Block (定义int a后)
15     // NSStackBlock : 栈Block
16     
17     NSLog(@"第三种Block %@",^{
18         NSLog(@"%d",a);
19     });

 

二. Block循环引用

假设A控制器跳转至TargetViewController, 如果目标控制器内有block造成循环应用, 当从TargetViewController返回时, TargetViewController不会调用析构方法(dealloc方法). 这就造成了内存泄漏. 下面列出三种方法消除循环引用.

 1 #import "TargetViewController.h"
 2 
 3 // typedef void(^LHBlock)(void);
 4 typedef void(^LHBlock)(TargetViewController *);
 5 
 6 @interface TargetViewController ()
 7 
 8 /** 说明 */
 9 @property (nonatomic, copy) LHBlock block;
10 /** 说明 */
11 @property (nonatomic, copy) NSString *name;
12 
13 @end
14 
15 @implementation TargetViewController
16 
17 - (void)viewDidLoad {
18     [super viewDidLoad];
19     
20     self.view.backgroundColor = [UIColor whiteColor];
21     
22     self.name = @"my name";
23     
24     // 使用__weak,就是告诉系统,这是个循环应用,所以不用调用,就会释放
25 //    __weak typeof(self) weakSelf = self;
26 //    self.block = ^{
27 //        NSLog(@"%@",weakSelf.name);
28 //        // 延长寿命周期,strong
29 //    };
30     
31     
32     // 要在block里面置为nil,并且必须调用,否则不会置为nil,还是会造成循环应用
33 //    __block TargetViewController *weakVC = self; // 重新拷贝一份
34 //    self.block = ^{
35 //        NSLog(@"%@",weakVC.name);
36 //        weakVC = nil;
37 //    };
38 //    self.block();
39     
40     // 为什么会产生循环引用
41     // self -> block -> vc
42     // 这样不会产生循环应用,vc只是临时变量,只在作用域内有效,出来就释放了
43     self.block = ^(TargetViewController *vc) {
44         NSLog(@"%@",vc.name);
45     };
46     // 调不调用block都会走析构方法
47     self.block(self);
48     
49 }
50 
51 - (void)dealloc {
52     NSLog(@"dealloc");
53 }
54 
55 @end

 

三. Block底层原理

通过终端编译出block运行时所执行的代码.

1.创建出block.c的文件

vim: 进入编辑模式

输入":"进入输入台

wq: 保存并退出vim模式

2.在block.c的文件中输入如下代码:

 1 #include "stdio.h"
 2 int main () {
 3     
 4     int a = 10;
 5     
 6     void(^block)(void) = ^{
 7         
 8         printf("%d",a);
 9     };
10     
11     block();
12     
13     return 0;
14 }

 3. 终端输入, 多出a.out文件, 可以执行运行结果.

 1 gcc block.c 

4. 终端继续输入, 生成编译代码.

 1 clang -rewrite-objc block.c 

最终结果如下:

双击打开block.cpp文件.

5. 上面是消息转发,看不懂. 一直往下翻往下翻,翻到570行左右.

看出main函数的执行操作

看出a值是通过值拷贝,拷贝到block中.

看出block也是对象,符合对象的规定,有isa指针.

 

6. 同样的步骤,将block.c中的代码修改为:(__block)

 1 #include "stdio.h"
 2 int main () {
 3     
 4     __block int a = 10;
 5     
 6     void(^block)(void) = ^{
 7         
 8         printf("%d",a);
 9     };
10     
11     block();
12     
13     return 0;
14 }

查看block.cpp文件,发现block中的操作有些不同:

 

 

这就是为什么加了__block就有了修改变量的权限.

 

四. Block应用

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     
 4     // block应用: 链式编程+函数编程
 5     // 通过点语法,串联操作
 6     // 返回值block
 7     NSLog(@"%@",self.select.where(@"all 牛"));
 8     
 9     // get方法 + 参数
10     // viewDidLoad : 数据 --> 方法:sel(方法选择器) --> imp --> 函数
11     // 方法: 函数 : 给某个对象发送消息 _cmd
12     
13     // block 参数
14     // 函数式: y = f(x) ---> y = f(f(x))
15     
16     [self functionBlock:^(NSString *word) {
17         NSLog(@"%@",word);
18     }];
19     
20 }
21 
22 #pragma mark - 函数式Demo
23 - (void)functionBlock:(void(^)(NSString *))success {
24     if (success) {
25         // 灵活 异步
26         success(@"hello 函数式");
27     }
28 }
29 
30 #pragma mark - 链式Demo
31 - (ViewController *)select {
32     NSLog(@"select");
33     return self;
34 }
35 
36 - (NSString *(^)(NSString *))where {
37     NSLog(@"where");
38     
39     NSString *(^block)(NSString *) = ^(NSString *word) {
40         return [NSString stringWithFormat:@"ken:%@",word];
41     };
42     
43     return block;
44 }

 

这里只是block初探,有兴趣可以深入研究.

 

转载于:https://www.cnblogs.com/discipline/p/10174538.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值