ios学习笔记——Block块小结

一、块的基础知识


块与函数类似。尤其跟函数指针非常相思,用法也大同小异。

块的语法结构如下:

return_type  (^block_name)(parameters)

返回类型    块名称    参数

1     //定义块
2     int (^sjzBlock)(int a, int b) = ^(int a, int b){
3         return a + b;
4     };
5     //使用块
6     int c = sjzBlock(1, 2);

 

在声明块的范围内,所有变量都可以为其所捕获。但是不能修改变量,如果想要修改,可以在声明变量的时候加上__block修饰符。

 1     //在块里修改e的值,报错
 2     int e = 100;
 3     //加上__block修饰符,可以修改d的值
 4     __block int d = 10;
 5     int (^sjzBlock)(int a, int b) = ^(int a, int b){
 6         d = 12;
 7 //        e = 90;  //报错
 8         return a + b;
 9     };
10     int c = sjzBlock(1, 2);
11     NSLog(@"c = %d  d = %d", c, d);

输出结果:

 

块本身也是一个对象,也有引用计数。

如果块所捕获的变量是对象类型,那么就会自动保留它。系统在释放这个块的时候,也会将其一并释放。

块可以访问类的所有实例变量,块能够修改实例变量,所以在声明实例变量时,无需加__block。如果通过读取或写入操作捕获实例变量,那么也会自动把self变量一并捕获了,因为实例变量是与self所只带的实例关联在一起的。当块保留self的时候,很可能self也保留了块,容易造成循环引用。

 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @property (nonatomic, strong) NSString * sjzStr;
 6 
 7 @end
 8 
 9 @implementation ViewController
10 
11 - (void)viewDidLoad {
12     [super viewDidLoad];
13     
14     [self blockText];
15 }
16 
17 - (void)blockText
18 {
19     void (^sjzBlock)(int a, int b) = ^(int a, int b){
20         //以下这两种调用,都会将会捕获self
21 //        _sjzStr = @"Hello, world";
22         self.sjzStr = @"hello, world";
23         NSLog(@"%@", _sjzStr);
24     };
25     
26     sjzBlock(1, 2);
27 }
28 
29 @end

 

 

块的内部结构


 

这里面,最重要的是invoke变量,是一个函数指针,指向块的实现代码。至少接受一个void*类型的参数,此参数代表块本身。

descriptor变量是指向结构体的指针,每个块都包含改结构体。声明了块的总体大小,copy函数指针保留捕获的对象,dispose当块释放时,释放捕获的对象。

块会把它捕获的对象全部拷贝一份,捕获了多少对象,就要占据多少内存空间。

posted @ 2016-03-10 11:04  sjzLovecj  阅读(229)  评论(0编辑  收藏  举报