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 });
假设A控制器跳转至TargetViewController, 若是目标控制器内有block形成循环应用, 当从TargetViewController返回时, TargetViewController不会调用析构方法(dealloc方法). 这就形成了内存泄漏. 下面列出三种方法消除循环引用.vim
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运行时所执行的代码.异步
1.建立出block.c的文件函数
vim: 进入编辑模式atom
输入":"进入输入台spa
wq: 保存并退出vim模式3d
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文件, 能够执行运行结果.code
1 gcc block.c orm
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就有了修改变量的权限.
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初探,有兴趣能够深刻研究.