Block
Block块语法
一、认识Block
一种认为 Block本身就是一个对象
一种认为Block 是一个封装了C语言的一个代码块
Block的底层实现 是用C来写的
效率更高 苹果公司 现在推荐的使用
二、语法
声明
返回值 (^ 名称 )(参数类型 );
实现
名称 = ^(参数类型 形参){
//大括号里面 写 block里面需要执行的代码
};
通常 声明 实现写到一起
void (^sumBlock)(int, int)=^(int a,int b){
int sum = a+b;
NSLog(@"%d",sum);
};
调用的时候
名称(参数);
sumBlock(3,4);
三、block的变量的三种使用
//1、不使用任何 外部的 变量
void (^block) (int)=^(int a){
printf("%d\n",a);
a++;
printf("%d\n",a);
};
block(2);
//2、使用外部变量 而且这个变量是 局部的变量
//不能改变 这个局部变量的值
//如果想要再block内部改变 那么使用__block修饰符
__block int a =5;
void (^aBlock) (void)=^{
a++;
printf("....%d\n",a);
};
aBlock();
//3、如果使用的外部变量 是全局变量 static或者 直接声明在全局
//可以直接使用 修改值的
void (^bBlock)(void)=^{
b++;
printf("%d\n",b);
};
bBlock();
四、可以使用typedef 进行自定义block
typedef void (^myBlock) (int,int);
自定义的block类型名称
myBlock block=^(int a,int b){
};
五、1、Block做函数参数
+(void)haveClass :(Block)b;
2、Block做属性 会引起循环引用
使用 copy
Block 默认声明是在栈上
使用copy能够把Block到堆
block的持有者 在block中使用的时候 会引用计数加1
__weak typeof(self) weakSelf =self;
self.b=^{
//如果 在内部使用 自身的持有者
weakSelf.age = 10;
};
循环引用 靠经验来解决
简单来说 A B A持有了B B持有了A
当A释放的时候 1 A没有dealloc
当B释放的释放 1 B也没有dealloc
当A持有B B持有A 最终成了内存泄露 这种情况就是循环引用
现阶段
A类里面 导入B类 #import
B类里面 导入A类
这也是一种循环引用
代理 @property (nonatomic, weak) id< >delegate;
六、Block的作用
1、封装了一个代码块 可以在任何的时候 进行调用。
2、BLock含有返回值 参数 很多情况下 代替 方法 函数来使用。
3、Block多用于 数组 字典 集合等类的遍历、多线程的数据返回、异步通信、动画转场 、界面跳转。
4、回调
//声明
//1、返回值为空 参数为空的
// void (^block) (void);
//返回值 名称 参数(仅写类型)
//2、有返回值 参数为空
int (^myBlock) (void);
//3、无返回值 多个参数的
void (^newBlock) (int ,int);
//实现
//1、返回值为空 参数为空的
void (^block) (void) = ^{
//block调用的时候 执行的代码
printf("我是block");
};
//2、有返回值 参数为空
// int (^myBlock) (void)= ^{
// return 3;
// };
myBlock = ^{
return 3;
};
//3、无返回值 多个参数的
// void (^newBlock) (int ,int);
newBlock = ^(int a, int b){
int sum = a+b;
printf("%d",sum);
};
//通常 写的时候 声明和实现 写在一起
void (^aBlock)(int) = ^(int a){
//写调用block的 执行的代码
printf("%d",a);
};
//调用aBlock
// aBlock(3);
//使用block求俩个数的和
int (^sumBlock)(int, int)=^(int a,int b){
int sum = a * b;
return sum;
};
//调用求和的block
int ret= sumBlock(3,4);
NSLog(@"%d",ret);