Block的骨干采纳

一.block的简单使用

前言

block是C语言的扩充功能,用一句话来解释就是:带有自动变量(局部变量)的匿名函数,就是不带有名称的函数。其实block的定义有点像函数指针,很多语言其实都有类似block的概念。

1.Block代码块的基本使用

  • Block的作用

    • Block主要用来保存一段代码
    • Block可以封装一段代码,这段代码可以在任何时候调用执行
  • Block能够作为函数的参数或者函数的返回值,Block自已也可以 包含参数和返回值

  • 定义Block语法格式

   ^(block 返回值类型)(参数类型:参数1,参数类型:参数2,...)
     {

         //block 执行代码

     }

注意

  • Block 必须以 ^ 开头---- ^ block 的标志
  • Block 返回值类型可以省略
  • Block 不用指定名字
  • 没有参数时候,参数部分( )不能省略,一般使用void
  • 定义Block变量
 block返回值类型 (^ block 变量名)(参数类型1,参数类型2,...);

** 注意 **

声明block变量,只需要指定参数类型

** 注意区分 Block 块和 Block 块变量,我们是将 Block 块赋值给Block 块变量 **

  • Block与函数
    保存代码;有返回值;有形参;调用方式一样
 //1.没有返回值,没有形参
    void (^ printBlock)(void) = ^{

        NSLog(@"printBlock");
    };

    printBlock();//注意调用的时候,不要忽略( )

 //2.有参数,有返回值
  int(^printTest)(int ,int) = ^(int a, int b){
        return a * b;
    };

    NSLog(@"%d",printTest(3,3));

//3.
    void(^print)(NSString * str);

    print = ^(NSString * str){
        NSLog(@"%@",str);
    };

    print(@"block其实没有那么难");

    void(^printA)(int) = ^(int a)
    {
        NSLog(@"-------");
    };

    printA(5);
  • 我们可以先定义块变量,再对块变量进行赋值;也可以定义块变量的同时对块变量赋值
  • 注意书写block时,最好先写block代码块,再写block变量

1.Block入门

Block是C语言的扩充功能。简单的来说:Block就是带有自动变量(局部变量)的匿名函数。这个可以类比C语言的函数指针。Block有着灵活和强大的功能,而且不需要命名。Block其实就是一个代码块,把你想要执行的代码封装在这个代码块里,等到需要的时候再去调用。那block是OC对象吗?答案是肯定的。这里把学习Block的过程记录下来。

1.block声明

block变量的声明格式为: 返回值类型 ;

  • 声明一个无返回值,有两个NSString参数,名字为ablock的blockvoid (NSString * str1,NSString * str2);

  • 形参变量名可以省略,只留下形参类型void (NSString * ,NSString * );

block语法

block的基本语法形式是:
^ 返回值类型 参数列表 表达式
例如:

^ int (int num) {return num  1;}

^ int (int num1,int num2) {return num1   num2;}

有时候我们可以省略其中的几项,首先是返回值,如果表达式中没有返回值时,也就是说没有return语句的时候返回值类型是可以省略,例如:

^ (int num) {NSLog(@"数字:%@",num);}

没有参数的时候,参数列表也是可以省略的

^ int {return 10*10;}

甚至有时候返回类型和参数列表都可以省略

^ {NSLog(@"这是一段代码");}

2.Block与局部变量

  • Block能够访问局部变量的值
  • Block改变局部变量的值,必须给局部变量加上__block修饰符
 int num = 25;
    void (^printNum)(void) = ^(void)
    {
        NSLog(@"%d",num);
    };

    num = 35;
    printNum();
//程序输出的是25,而不是35
  • 在使用block访问局部变量的时候,当我们定义block的时候,就会把局部变量的值保存在block中,并不是当我们调用block的时候才去获取局部变量的值
 __block int num = 25;
    void (^printNum)(void) = ^(void)
    {
        num = 40;
        NSLog(@"%d",num);

    };

    num = 35;
    printNum();
//程序输出的是40
  • 当我们使用__block修饰局部变量:任何时候,程序都是直接访问局部变量本身,不是将局部变量的值赋值到block范围内

图片 1

block内部直接修改局部变量报错

1.1 Block的语法:

^ 返回值类型 参数列表 表达式

上面就是典型的block语法规范,举个简单例子:

^ NSInteger (NSInteger num1, NSInteger num2) {
            return num1   num2;
        };// 一个返回num1   num2 的简单block

当然block语法可以省略,当返回值或参数列表为void时就可以省略,例子如下:

        ^(int count){count  ; };// 等价于 ^void (int count){ count  ; };

        ^{printf("hello block");}; //等价于 ^void (void){ printf("hello block"); };

block语法还可以省略返回值类型,这是因为表达式中含有return语句时,其返回值类型必须与其一致,基于这种特性,我们可以省略返回值类型,简单样例如下:

^(int count){ return count  ; };// 等价于^int (int count){ return count  ; };   
2.block赋值

block的赋值格式为: ablock变量=^{函数体} ;

 //1.在此先声明一个名为ablock的block void (NSString * str1,NSString * str2); //2.在此将等号右边的block代码块的实现赋值给ablock变量 ablock = ^(NSString * str1,NSString * str2){ NSLog(@"%@,%@",str1,str2); }; //3.在这里调用ablock ablock(@"lisj",@"ddsd");

block 赋值格式``block变量 = ^返回值类型{函数体};

  • 其中,返回值类型可以书省略,因为编译器可以根据存储代码块的变量中,确定返回值的类型.

block类型变量

那如何声明一个block类型的变量呢
返回值类型 (^变量名) (参数类型列表)
例如:

int (^oneBlock) (int);

int (^oneBlock) (int,int);

如何给变量赋值呢

int (^oneBlock) (int) = ^ int (int num) {return num  1;};

而且变量之间也可以互相赋值

int (^oneBlock1) (int) = oneBlock;

3.Block作为方法的参数

  • 当我们把block用作方法的参数时,不用定义block变量,直接将block作为参数传递给相应方法就可以
  • 苹果官方建议block通常作为最后一个参数
1.2 Block作为类型变量:

在C语言中,我们知道声明一个函数指针的语法模式如下:

int func(int count) {
    return count  ;
}

int (*funcPtr)(int) = &func;

同样的,block的语法类似:

 int (^func)(int) = ^ (int count) {
                           return count  ;
                      };

既然可以作为变量,那么用法就会非常灵活,我们可以在函数返回和使用block变量,可以将block作为函数参数,实例如下:

      // 定义几种类型的block
    typedef void (^blk_1) (void);
    typedef int (^blk_2) (void);
    typedef int (^blk_3) (int);

    // 1.作为函数返回;
    - (blk_1)func1 {
        return ^ {
            NSLog(@"block作为返回类型");
        };
    }
    //  2.作为参数

- (void)func2:(blk_3)blk {
    blk = ^ (int count){
        return count   ;
    };
}
3. 在声明block的同时对其进行赋值
  • 简化block的声明和定义的过程,一步到位,直接调用即可
//1.声明block,并定义 int   = ^ (int c,int d){ return c*d; };//2.有参数有返回值的block调用 NSLog(@"%d", myblcok;//这里会在控制台打印20
  • 如果没有参数列表,赋值时,参数列表可以省略
//1.无返回值无参数block的声明及定义 void (^oneblcok) () = ^ { NSLog(@"hello world ");//打印hello world };//2.无参,无返回值block的调用 oneblcok();

自定义block类型

我们可以利用typedef来定义一个block类型

typedef int (^BlockType)(int);

这样我们就可以直接使用BlockType作为类型来声明变量

BlockType oneBlock;
oneBlock = ^ int (int num) {return num  1;};

4.typedef定义block变量

  • 作用

  • 复用blcok变量类型,重复定义多个block变量

  • 使用block类型定义函数参数

  • 格式

typedef block返回值类型 (^block变量类型)(参数类型1 参数名,参数类型2,参数名)

 //使用typedef定义块变量类型
    typedef void (^ZZYPrint)(NSString * str);

    //使用ZZYPrint定义块变量,并将指定block代码块赋值给该变量
    ZZYPrint  print1 = ^(NSString * str){
        NSLog(@"%@",str);
    };

    ZZYPrint print2 = ^(NSString * str)
    {
        NSLog(@"%@",str);
    };

    print1(@"print1");

    print2(@"print2");

    //利用typedef定义的块变量类型即可为函数声明块变量类型的形参,要求传入参数时必须传入块变量
1.3 blcok赋值

block的赋值

格式:block = ^返回值类型(参数列表){}

没有参数没有返回值

myBlock testBlock = ^void(){
     NSLog(@"test");
 };
 // 没有返回值,void可以省略
myBlock testBlock1 = ^(){
     NSLog(@"test1");
 };
 // 没有参数,小括号也可以省略
 myBlock testBlock2 = ^{
     NSLog(@"test2");
 };

有参数没有返回值

myBlock1 testBlock = ^void(NSString *str) {
      NSLog(str);
}
//省略void
myBlock1 testBlock = ^(NSString *str) {
      NSLog(str);
}

有参数有返回值

myBlock2 testBlock = ^NSString *(NSString *str) {
     NSLog(str)
     return @"hi";
}
//有返回值时也可以省略返回值类型
 myBlock2 testBlock2 = ^(NSString *str) {
     NSLog(str)
     return @"hi";
}

二.block的进阶使用

  • 第一种语法
//1.声明一个求和函数 void useBlockInC(int (int a ,int b)){ NSLog(@"%d",block;}//2.定义一个block,用来实现求和的功能(主要逻辑部分,根据自己的需求在这里写代码) int (^addBlock)=^(int x,int y){ return x y; };//3.调用函数 useBlockInC;
  • 第二种语法(第一种的简化版--常用)
    • 将第一种语法中的第2步和第3步结合起来,简化语法
//1.声明一个求和函数 void useBlockInC(int (int a ,int b)){ NSLog(@"%d",block;}////简化,把2和3结合起来,简化之后如下方式//示例1 useBlockInC(^int(int a, int b) { return a*b;//这里的代码逻辑根据项目需求写,可灵活多变,只要符合语法 });//示例2 useBlockInC(^int(int a, int b) { return a-b;//比如变成减法 });
  • block用作函数参数,相当于传进来了一种数据类型,可以拿到相应的参数来做自己想做的事.
  • block一般用作函数参数时,多为无返回值类型.
  • 第一种语法
//1:写自己需要用到block做参数的函数-useBlockInOC:(NSDictionary * dic))block{ block(@{@"name":@"myName is bob"});}//2:声明一个block变量,并把具体的代码块赋值给block变量 void (^dicBlock) (NSDictionary *) = ^(NSDictionary * dic){ for (NSString * item in dic) { NSLog(@"%@",item); } };//3:调用函数,将block当做参数传入函数 [self useBlockInOC:dicBlock]; 
  • 第二种语法
    • 简化版(第二步和第三步合并)
//1:写自己需要用到block做参数的函数-useBlockInOC:(NSDictionary * dic))block{ block(@{@"name":@"myName is bob"});}//2.调用函数,代码块内写逻辑代码 [self useBlockInOC:^(NSDictionary *dic) { NSLog(@"%@", [dic objectForKey:@"name"]); }];

//第一步,使用typedef声明block类型typeBlock typedef void (^typeBlcok) (NSArray *);//第二步,创建一个block的变量,并把block的代码块赋值给这个新创建的变量 typeBlcok newBlcok =^(NSArray * arr){ for (id item in arr) { NSLog(@"%@",item); } };//第三步:调用block,记得传入参数 NSArray * arr=@[@"战狼2",@"吴京",@"敦刻尔克",@"蜘蛛侠",@"极限挑战",@"美丽的五险",@"你好,佳人",@"成语大会",@"创业故事"]; newBlcok;//调用block
  • 第一种语法
//1.使用typeBlock声明一种block的类型,简化block的用法typedef void(^typeBlock) (NSDictionary * dic);//2.写自己需要的函数-useBlockInOC:(NSDictionary * dic))block{ block(@{@"name":@"myName is bob"});}//3.用声明的typeBlock类型创建一个block变量,然后把具体的代码块赋值给对象 typeBlock block = ^(NSDictionary *dic) { NSLog(@"%@", [dic objectForKey:@"name"]); }; //4.调用函数,将block当做参数传入函数 [self useBlockInOC:block]; 
  • 第二种语法
//1.使用typeBlock声明一种block的类型,简化block的用法typedef void(^typeBlock) (NSDictionary * dic);//2.写自己需要的函数-useBlockInOC2:(typeBlock)block{ block(@{@"name":@"myName is bob"});}//3.调用函数,简化版,代码块内直接写逻辑代码 [self useBlockInOC:^(NSDictionary *dic) { NSLog(@"%@", [dic objectForKey:@"name"]); }];

解释:无论是C语言或者是OC语言,第二种语法最常用.第一种语法可以看做是第二种语法的来源或者原理

将block类型作为函数参数

我们也可以将block类型的参数向函数中传递

 - (void)func:(BlockType)block{
    NSLog{@"number:%d",block(2)};
}

1.4 block作用

block是用来封装一段代码,这段代码可以在任何时候调用

与C中指向函数的指针 类似处

block可以做为方法/函数的参数与返回值
block可以接收参数与返回值

与C中指向函数的指针 不同处

block是inline的,并且对局部变量是只读的;

__block说明符

如果想在block的表达式中,给block语法外声明的变量赋值,需要在变量前加__block说明符。

__block int num = 0;
void (^oneBlock)(void) = ^{
    num = 1;
}

再来看以下代码

NSMutableArray * array = [[NSMutableArray alloc] init];
void (^oneBlock)(void) = ^{
    id obj = [[NSObject alloc] init];
    [array addObject:obj];
}

这样是没有问题的,但是以下代码就有问题了

NSMutableArray * array = [[NSMutableArray alloc] init];
void (^oneBlock)(void) = ^{
    array = [[NSMutableArray alloc] init];
}

这样就出错了,这时需要在变量前加__block,如下

__block NSMutableArray * array = [[NSMutableArray alloc] init];
void (^oneBlock)(void) = ^{
    array = [[NSMutableArray alloc] init];
}

版权声明:出自MajorLMJ技术博客的原创作品 ,转载时必须注明出处及相应链接!

本文由星彩网app下载发布于计算机编程,转载请注明出处:Block的骨干采纳

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。