函数的一个重要做用:先把某一个代码存起来,你想用的时候调函数就能用了
可是函数有个缺点,它不能动态定义,不能执行完一行忽然定义一个函数。函数的代码
是死的,必定得在编译以前把函数写好,以前写的函数是什么,之后就是什么。
这个时候,block就出现了。
void (^block)() = ^{
//里面放的是代码
};
大括号表明代码块。^号意味着代码块用block存储。函数
void (^block)() 跟 函数 void play () 很像,
只是函数的名称play换成了block的名称(^block)指针
对比函数,block有一个好处,比较灵活,能够在外面定义(这时是全局变量),也可
以在里面定义(这时是局部变量),而函数只能在外面定义。对象
block跟函数同样,有返回值,有参数。
没有参数的block
//等号右边没有括号是由于没有参数,不须要写。
void (^block)() = ^{
//代码
}blog
block先把大括号里的代码块存起来,想执行里面的代码的时候,本身来调用。
问:如何调用没有参数的block?
答:block(); 内存
有参数的block
int (^sumBlock)(int.int) = ^(int a,int b){
return a + b;
}
问:如何调用有参数的block?
答:int r = sumBlock(10,2); 编译
格式:
返回值(^Block变量名)(参数类型) = ^(参数类型+形式参数){
//代码
}变量
给Block起别名
错误写法:typedef int (^sumBlock)(int.int) MyBlock;
正确写法:typedef int (^MyBlock)(int.int);循环
问:如何定义起别名以后的block?
//用MyBlock类型来定义sumBlock变量,来保存下面这些代码。
答:MyBlock sumBlock = ^(int a,int b){
return a + b;
}引用
MyBlock minusBlock = ^(int a,int b){
return a - b;
}
PS:MyBlock为Block的类型,sumBlock和minusBlock为Block的变量名(用变量名
来保存代码)
那sumBlock和minusBlock是什么类型呢?
是返回值为int,有2个int类型参数的MyBlock类型。方法
block有一个特色,block里面若是用了外部的一些变量什么的(好比self),它会对这
个self产生一个强引用。也就是说,block会对控制器产生强引用。这样会造成内存泄露
。意味着有些对象你根本不可能释放。(缘由在于引起了循环引用)
PS:_age和self.age同样,都会致使循环引用 _age等价于self->_age
解决方法:将block指向控制器的箭头改成弱指针。
第一种作法:
__unsafe_unretained MJShareViewController *selfVc = self;
而后将方法内这句代码以后的self所有改成selfVc便可。
第二种方法:
__weak MJShareViewController *selfVc = self;
__weak typeof(self) selfVc = self; //这样写更好,没必要管控制器是什么类型。
注意:typeof(self)等价于MJShareViewController * 都是控制器的类型。
而后将方法内这句代码以后的self所有改成selfVc便可。
PS: __weak功能更多。能够防止野指针,一旦发现野指针,会自动变成空指针。