//带有自动变量值的匿名函数
//block 与 C语言函数比只有两点不同,1.没有函数名。 2.带有“^”。
//类似于方法,如B中的值传给A中,在B中,一. 定义 ; 二. 实现。 在A中. 一. 调用。
一、Block是什么?
- 匿名函数
- 截获自动变量
二、Block语法。
---1.语法
1. ^ 参数列表 表达式
2. ^ 参数列表 表达式
3. ^ 表达式
4. 完整block详细图。
(返回类型)(^block名称)(参数类型)=^(参数列表){代码实现};
。
--- 自动变量的截获取
int a = 256; const NSString *loves = @"val ================> %d "; void (^STR)(void) = ^{ NSLog(loves,a); }; //调用 a = 100; loves = @"------------------I love You-----------------"; STR(); //实现
---2. __block 说明符
1.block对外部变量是只读的,要变成可读可写,就需要加上__block
2.将栈中的block复制到堆上一份,从而避免了循环引用这个情况
3.没有用__block 之前,自动变量的截获只能保存执行block语法瞬间的值。
4.block 转c++ clang -rewrite-objc 源代码文件名。
5. __block 可以指定任何类型的自动变量。
6.对于用__block修饰的外部变量引用,block是复制其引用地址来实现访问的。
注意:如果是全局变量的话,可以直接赋值,不用加__block ;
NSInteger i = 0; void (^blk)() = ^{ //Variable is not assignable (missing __block type specifier),编译器报错,变量未加__block,不能给自动变量(外部变量/局部变量)赋值. // i = 2; };
可以在block内给自动变量赋值(外部变量/局部变量)。
--- 实现//改成这样
__block NSInteger let = 0; //调用 void (^labels)() = ^{ //Variable is not assignable (missing __block type specifier),编译器报错,变量未加__block,不能给自动变量(外部变量/局部变量)赋值. let = 2; NSLog(@"let====》%ld",let); }; //实现 labels();
---3. __weak 说明符
//这个例子就造成了循环引用,(1)self(强引用)block. (2) 在block中又调用self的方法,block(强引用)self. 这样的话就造成循环引用
//self 对block引用 self.block = ^{ [self layouts]; // 在block中又调用self的方法,这样就造成了循环引用。 }
三、Block的用途及注意事项。
- 作为函数参数
- 反向传值
- 循环引用
- Block的使用注意
- block内部可以访问外部的变量,block默认是将其复制到其数据结构中来实现访问的。
- 默认情况下,block内部不能修改外面的局部变量,因为通过block进行闭包的变量是const的。
- 给局部变量加上
__block
关键字,这个局部变量就可以在block内部修改,block是复制其引用地址来实现访问的。
- Block作为属性应该用copy修饰
- 当用weak、assign修饰block属性时,block访问外部变量,此时block的类型是栈block。保存在栈中的block,当block所在函数方法返回结束,该block就会被销毁。在其他方法内部调用访问该block,就会引发野指针错误
EXC_BAD_ACCESS
。 - 当用copy、strong修饰block属性时,block访问外部变量,此时block的类型是堆block。保存在堆中的block,当引用计数器为0时被销毁,该类型block是由栈类型的block从栈中复制到堆中形成的,因此可以在其他方法内部调用该block。在ARC下,
strong
和copy
都可以用来修饰block,但是建议修饰block属性使用copy
。
四.所有栗子:
//(1)定义无参无返回值的Block void (^noneBack)() = ^(){ NSLog(@"定义无参数无返回值的block"); }; noneBack(); //(2)定义有参数无返回值的Block void (^oneBack)(NSString *str) = ^(NSString *strs){ NSLog(@"%@",strs); }; oneBack(@"我是一个参数的block"); //(3)定义有参数int返回值的Block int (^intBack)(int ,int) = ^(int a,int b){ return a+b; }; int sum = intBack(100,200); NSLog(@"a+b== %d",sum);
五.block在其它语言的说法