block总结

1.是什么?

一种特殊的数据类型

2.有什么用?

用于保存代码块

3.怎么用?

>1.声明block的快捷键:

inlineBlock

>2.block的声明:

    <#returnType#>(^<#blockName#>)(<#parameterTypes#>) = ^(<#parameters#>) {
        <#statements#>
    };

>3.声明/初始化/调用

    //声明
    void(^myBlock1)();//无参无反
    int(^myBlock2)();//无参有反
    void(^myBlock3)(int);//有参无反
    int(^myBlock4)(int,int);//有参有反

    //初始化
    myBlock1 = ^()
    {
        NSLog(@"无参无反");
    };

    myBlock2 = ^()
    {
        return 3;
    };

    myBlock3 = ^(int a)
    {
        NSLog(@"%d",a);
    };

    myBlock4 = ^(int a,int b)
    {
        return a + b;
    };

    //调用
    myBlock1();
    int num = myBlock2();
    myBlock3(3);
    int sum = myBlock4(3,4);

>4.给block起别名

返回值类型 (^别名)(参数);

例:

typedef void(^myBlock)();//给第一个无参无反的block起别名myBlock,myBlock就称为一种数据类型

使用:

  myBlock block1 = ^(){
        NSLog(@"声明和定义不同,声明仅仅是声明一个变量(开辟一块内存空间),并不初始化,定义包含了初始化,像这样即是声明的同时初始化了");
    };

像这样仅仅是声明了一个myBlock类型的变量:

    myBlock block2;
    myBlock block3;
    myBlock block4;

因为block是一种数据类型,因此数据类型所具有的所用特性block都具有,可以声明变量;作为参数;作为返回值;

>5.block作为函数参数

>例一:

typedef int(^myBlock2)();
typedef int(^myBlock3)(int);
 int sum(myBlock2 m,myBlock3 n,int a)//a为myBlock3需要的参数
{
//    int num1 = m();
//    int num2 = n(a);
//    return num1 + num2;
    return m() + n(a);
}
    //block作为函数参数
    myBlock2 m = ^(){
        return 10;
    };

    myBlock3 n = ^(int a)
    {
        return a;
    };

    int num = sum(m, n, 10);

    NSLog(@"%d",num);//输出20;

此种方式并不常用.常用的情景是:比如有三个函数,开头和结尾部分执行的代码一样,中间有部分代码不同,那么就可以将中间部分抽取为block,将三个函数变为一个,调用三次该函数,传入不同的block即可.

>例二:

 
void test1() {

    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
    NSLog(@"星期天,今天去哪儿浪呢?");
    
    NSLog(@"BBBBBBBBBBBBBBBBBBBB");
    
    
}

void test2() {
    
    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
    NSLog(@"星期一,昨天玩的好累不想上班.");
    
    NSLog(@"BBBBBBBBBBBBBBBBBBBB");
    
}

void test3() {
    
    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
    NSLog(@"星期二,昨天的任务还没完成");
    
    NSLog(@"BBBBBBBBBBBBBBBBBBBB");
    
}

通过block优化,分析中间部分代码,不需要参数,返回值,定义无参无反的block:

typedef void(^myBlock)()

将四个函数抽取为一个

void test(myBlock myLife) {
    
    NSLog(@"AAAAAAAAAAAAAAAAAAAA");
    
  if(myLife){//判断block是否为nil,否则可能报错,会报什么错呢?,为什么是nil呢,nil不是用于OC对象为空的情况么?block是基本数据类型?还是OC类型?
myLife();
  } NSLog(
@"BBBBBBBBBBBBBBBBBBBB"); }

main函数中就可以这样写:

 test(^(){
     NSLog(@"星期天,今天去哪儿浪呢?");
 });
 test(^(){
     NSLog(@"星期一,昨天玩的好累不想上班.");
 });
 test(^(){
     NSLog(@"星期二,昨天的任务还没完成");
 });

>6.作为函数返回值

typedef void(^myBlock)();

myBlock test4()
{
    return ^(){

    };
}

>7.利用block在不同对象间进行传值

假设A需要传值给B,那么需要在A中定义一个block属性,在需要的时候传递值,先判断是否为nil,不为nil则调用block.

需要在B中声明一个属性(有东西接收就可以,不一定就要定义属性),用以接收传递过来的值,B必须拿到A,比如A成为B的属性,那么就可以获取A的block属性,并定义,判断的时候,block就已经定义了,就可以实现传值了.

例子:

控制器的View上有一个绿色的View,当点击屏幕的时候,传递一个NSInteger数据给控制器.

分析:

绿色的View为数据的传递者,控制器为接收者,因此,需要给绿色的View声明一个block类型的属性,因此自定义一个GreenView的类用于描述绿色的View,并在其中声明block属性

typedef void(^GreenViewBlock)(NSInteger index);
@property (nonatomic,copy) GreenViewBlock myBlock;

当点击屏幕的时候传递数据,因而重写touchesBegin方法

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (_myBlock) {//如果实现了,就调用
        _myBlock(11);
    }
}

控制器为接收者,因而给控制器声明一个属性用于接收数据,又因为,需要在控制器中初始化block,这样点击屏幕是block不为nil,实现传值,因而需要获得绿色的View的属性block,因而,将绿色的View拖成控制器的属性

@property (nonatomic,assign) NSInteger index;

@property (weak, nonatomic) IBOutlet GreenView *greenView;
//初始化block  
_greenView.myBlock = ^(NSInteger index){ self.index = index; };
//上面的赋值操作即是调用index的setter方法,因而此时即可获得传递过来的数据
- (void)setIndex:(NSInteger)index { _index = index; NSLog(@"%ld",index); }

>8.注意:

 block内部默认不能修改外部的局部变量

 用__block修饰局部变量,在block中就可以访问了.

 

 

posted @ 2016-03-10 15:10  Matrix_Neo  阅读(292)  评论(0编辑  收藏  举报