函数的一个重要作用:先把某一个代码存起来,你想用的时候调函数就能用了
但是函数有个缺点,它不能动态定义,不能执行完一行突然定义一个函数。函数的代码
是死的,一定得在编译之前把函数写好,之前写的函数是什么,以后就是什么。
这个时候,block就出现了。
void (^block)() = ^{
//里面放的是代码
};
大括号代表代码块。^号意味着代码块用block存储。
void (^block)() 跟 函数 void play () 很像,
只是函数的名称play换成了block的名称(^block)
对比函数,block有一个好处,比较灵活,可以在外面定义(这时是全局变量),也可
以在里面定义(这时是局部变量),而函数只能在外面定义。
block跟函数一样,有返回值,有参数。
没有参数的block
//等号右边没有括号是因为没有参数,不需要写。
void (^block)() = ^{
//代码
}
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功能更多。可以防止野指针,一旦发现野指针,会自动变成空指针。