-
Block类型是一个C级别的语法和运行机制。
实例:
//定义有返回值和参数的block
int (^sumBlock2)(int x, int y) = ^ int (int a, int b) {
return a + b;
};
//调用有返回值的block
NSLog(@"%d", sumBlock2(4, 8));
- typedef使用
//给无参无返回值block变量起别名;
//格式: void (^新类型名)();
typedef void (^newType)();
//用新的类型定义block变量 newType t1;
t1 = ^{
NSLog(@"我是使用newType定义出来的变量t1的值");
};
//调用block
t1();
有参数有返回值的block起别名
//给有参数有返回值的block起别名
typedef int(^blockType2)(int ,int );
blockType2 b2 = ^(int x,int y){
return x>y?x:y;
};
//max保存的是代码块执行的结果
int max = b2(119,45);
- 函数指针
//调用函数
int s = sum(10, 119); //函数名存放的是函数的首地址
//定义函数指针
int (*p)(int a,int b); //p 函数指针变量
typedef int (*p1)(int a,int b); //给返回值是int 并且有两个参数的函数指针起一个别名 别名是p1 (是一个类型)
p = sum;
p1 = a
s = (*p)(10,119);
NSLog(@"s = %d",s);
访问外部变量
- 注意在block代码块的内部使用外部变量的时候注意
1)在block定义的时候,把block外部的变量的值copy到了内存的堆区
2)拷贝的过程中使用了const(以const的形式把外部变量做了一个copy)--要想修改值使用__block - 注意:一旦把使用__block修饰某个变量,注意block之后,使用的都是 堆区的变量
-
__block
修饰符 告诉编译器,i的值可以在block内部修改(忽略检查)
block作为函数参数
//通过函数,传递一个参数,
void test(void (^myblock)()){
if (myblock) {
//调用block
myblock();
}
}
//两种方式实现
//定义一个代码块,打印
void (^b1)()=^{
NSLog(@"**********");
NSLog(@"**********");
NSLog(@"哈哈哈");
};
//调用
test(b1);
test(^{
NSLog(@"wwwwwwww");
});
block作为方法的返回值
//声明
typedef void(^blockType)();
-(blockType)test2;
//实现
-(blockType)test2{
return ^{
NSLog(@"test2 return block");
};
}
//调用
//返回值是block类型的方法
blockType b1 = [p test2];
b1();
三种类型的block
根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。 NSGlobalBlock:类似函数,位于代码段; NSStackBlock:位于栈内存,函数返回后Block将无效; NSMallocBlock:位于堆内存。
- 全局block (NSGlobalBlock),定义在函数外面的block是global的。
如果函数内部的 block,但是没有捕获任何自动变量,那么它也是全局的(ARC和MRC都一样)。 - 栈block
- 堆block 则是对栈block copy 得来。对全局block copy 不会有任何作用,返回的依然是全局block。
block类型变量内存管理参数为什么要使用 copy
1.不管在MRC还是在ARC,使用assign 修饰的block,都是栈block,栈block会被提前释放。
2.在ARC下 block类型的变量 strong 相当于 copy。但是我们不会直接写成strong 而是写成 copy
block的内存隐患
Block_copy(bb); //copy block到堆区(bb位于堆区了)
Block_release(bb); //释放b1的空间(b1已经是一个堆block)