首页 > 代码库 > Block

Block

Block简介

Block使用场景,可以在两个界面的传值,也可以对代码封装作为参数的传递等。用过GCD就知道Block的精妙之处。

 

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进行操作。

 

typedef int (^SumP)(int,int);//用typedef定义一个block类型

 

//利用typedef定义block来创建一个block变量

   SumP sumblock1 = ^(int a,int b){

       return a - b;

    };

   int d = sumblock1(10,5);

    NSLog(@"d = %d",d);

 

 

Block的定义格式

返回值类型(^block变量名)(形参列表) = ^(形参列表) {

};

调用Block保存的代码

block变量名(实参);

默认情况下,Block内部不能修改外面的局部变量
Block
内部可以修改使用__block修饰的局部变量

Block的模式

1.无参数无返回值的Block

2.有参数无返回值的Block

3.有参数有返回值的Block

 

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结合typedef使用

自己定义一个Block类型,用定义的类型去创建Block,更加简单便捷。

这里举例一个Block回调修改上一下界面的背景颜色。

ViewController1 控制器1,ViewController2 控制器2

控制器1跳转到控制器2,然后在控制器2触发事件回调修改控制器1的背景颜色为红色。

 

Demo

ViewController2的实现

#import <UIKit/UIKit.h>

@interfaceViewController2 : UIViewController

/**

 *  定义了一个changeColorBlock。这个changeColor必须带一个参数,这个参数的类型必须为id类型的

 *  无返回值

 *  @param id

 */

typedefvoid(^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];

}

Block