本章不会对 Block 做过多的实现研究。只是讲解基本的用法。纯粹基础知识。结合实际项目怎么去做举例。Block 使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等。用过 GCD 就知道 Block 的精妙之处。
Block 是一种比较特殊的数据类型。它可以保存一段代码,在合适的时候取出来调用。
ARC 情况下
1. 如果用 copy 修饰 Block,该 Block 就会存储在堆空间。则会对 Block 的内部对象进行强引用,导致循环引用。内存无法释放。
解决方法:
新建一个指针 (__weak typeof(Target) weakTarget = Target ) 指向 Block 代码块里的对象,然后用 weakTarget 进行操作。就可以解决循环引用问题。
2. 如果用 weak 修饰 Block,该 Block 就会存放在栈空间。不会出现循环引用问题。
MRC 情况下
用 copy 修饰后,如果要在 Block 内部使用对象,则需要进行 (__block typeof(Target) blockTarget = Target ) 处理。在 Block 里面用 blockTarget 进行操作。
返回值类型 (^block 变量名)(形参列表) = ^(形参列表) {
};
调用 Block 保存的代码
block 变量名 (实参);
默认情况下, Block 内部不能修改外面的局部变量
Block 内部可以修改使用__block 修饰的局部变量
1. 无参数无返回值的 Block
2. 有参数无返回值的 Block
3. 有参数有返回值的 Block
无参数无返回值的 Block
- /**
- * 无参数无返回值的Block
- */
- -(void)func1{
- /**
- * void :就是无返回值
- * emptyBlock:就是该block的名字
- * ():这里相当于放参数。由于这里是无参数,所以就什么都不写
- */
- void (^emptyBlock)() = ^(){
- NSLog(@"无参数,无返回值的Block");
- };
- emptyBlock();
- }
有参数无返回值的 Block
- /**
- * 调用这个block进行两个参数相加
- *
- * @param int 参数A
- * @param int 参数B
- *
- * @return 无返回值
- */
- void (^sumBlock)(int ,int ) = ^(int a,int b){
- NSLog(@"%d + %d = %d",a,b,a+b);
- };
- /**
- * 调用这个sumBlock的Block,得到的结果是20
- */
- sumBlock(10,10);
有参数有返回值的 Block
- /**
- * 有参数有返回值
- *
- * @param NSString 字符串1
- * @param NSString 字符串2
- *
- * @return 返回拼接好的字符串3
- */
- NSString* (^logBlock)(NSString *,NSString *) = ^(NSString * str1,NSString *str2){
- return [NSString stringWithFormat:@"%@%@",str1,str2];
- };
- //调用logBlock,输出的是 我是Block
- NSLog(@"%@", logBlock(@"我是",@"Block"));
自己定义一个 Block 类型,用定义的类型去创建 Block,更加简单便捷。
这里举例一个 Block 回调修改上一下界面的背景颜色。
ViewController1 控制器 1,ViewController2 控制器 2
控制器 1 跳转到控制器 2,然后在控制器 2 触发事件回调修改控制器 1 的背景颜色为红色。
ViewController2 的实现
- #import
- @interface ViewController2 : UIViewController
- /**
- * 定义了一个changeColor的Block。这个changeColor必须带一个参数,这个参数的类型必须为id类型的
- * 无返回值
- * @param id
- */
- typedef void(^changeColor)(id);
- /**
- * 用上面定义的changeColor声明一个Block,声明的这个Block必须遵守声明的要求。
- */
- @property (nonatomic, copy) changeColor backgroundColor;
- @end
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
- //声明一个颜色
- UIColor *color = [UIColor redColor];
- //用刚刚声明的那个Block去回调修改上一界面的背景色
- self.backgroundColor(color);
- }
- ViewController1的实现
- -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
- ViewController2 *vc =[[ViewController2 alloc]init];
- // 回调修改颜色
- vc.backgroundColor = ^(UIColor *color){
- self.view.backgroundColor = color;
- };
- [self.navigationController pushViewController:vc animated:YES];
- }
来源: