结合 函数指针
来理解
Block 也是一种数据类型(保存代码块)
定义一个 block
无参无返回值
void (^roseBlock) ();
// void : 代表block将来保存的代码没有返回值
// () : 代表block将来保存的代码没有形参
// (^roseBlock) : 代表reseBlock是一个block变量, 可以用于保存一段block代码
roseBlock = ^(){
NSLog(@"roseBlock 代码块");//roseBlock 代码块
};
// 要想执行block保存的代码, 必须调用block才会执行
roseBlock();
// 如果block没有参数, 那么^后面的()可以省略
void (^jkblock)(void);
jkblock = ^{
NSLog(@"jkblock 代码块");//jkblock 代码块
};
jkblock();
复制代码
有参数有返回值
int (^printBlock)(int);
//block是一种数据类型
printBlock = ^int (int num) {
for (int i = 0; i < num; i++) {
NSLog(@"----%d----",i);
}
return 1;
};
int result = printBlock(3);
NSLog(@"返回值----%d----",result);
复制代码
有参数 没有返回值
void (^block)(int) = ^void (int num) {
NSLog(@"---%d--",num);//---5--
};
block(5);
void (^block1)(int) = ^ (int num) {
NSLog(@"---%d--",num);//---15--
};
block1(15);
复制代码
无参数,有返回值
NSString * (^block)(void);
// block = ^NSString * (){ //写法1
// block = ^NSString * { // 写法2
block = ^{ //写法三
return @"Jakcie";
};
NSString * name = block();//name == Jakcie
NSLog(@"name == %@",name);
复制代码
block 注意事项
block可以访问外面的变量
int a = 10;
void (^myBlock)(void) = ^{
NSLog(@"a = %d", a);//a = 10
};
myBlock();
复制代码
默认情况下不可以在 Block 中修改外面变量的值
- block中的变量和外界的变量并不是同一个变量
- block中访问到了外界的变量, block会将外界的变量拷贝一份到堆内存中
- block中使用的外界变量是copy的, 所以在调用之前修改外界变量的值, 不会影响到block中copy的值
int a = 10;
NSLog(@"&a = %p", &a);//0x7ffeefbff4fc
void (^myBlock)(void) = ^{
//a = 50;//会报错:Variable is not assignable (missing __block type specifier)
NSLog(@"&a = %p", &a);//0x100662f70
NSLog(@"a = %i", a);//10
};
a = 20;
myBlock();
复制代码
(_ _block)修饰的变量,在Block内部可以修改外部的变量
- 不加
__block
是直传递 - 加
__block
是地址传递
__block int a = 10;
NSLog(@"外部&a = %p", &a);//0x7ffeefbff4f8
NSLog(@"外部&a = %p", &a);//0x7ffeefbff4f8
void (^myBlock)(void) = ^{
a = 50;
NSLog(@"内部&a = %p", &a);//0x1004690c8
NSLog(@"内部a = %i", a);//10
};
NSLog(@"外部&a = %p", &a);//0x1004690c8
myBlock();
NSLog(@"外部&a = %p", &a);//0x1004690c8
NSLog(@"外部a = %i", a);//50
复制代码
Block 存储在 堆中 还是 栈中?
-
默认情况下block存储在栈中, 如果对block进行一个copy操作, block会转移到堆中
-
如果block在栈中, block中访问了外界的对象, 那么不会对对象进行retain操作
-
但是如果block在堆中, block中访问了外界的对象, 那么会对外界的对象进行一次retain
如果在block中访问了外界的对象, 一定要给对象加上 __block
, 只要加上了 __block
, 哪怕block在堆中, 也不会对外界的对象进行retain
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END