iOS-block的演示

  1. 会如何定义一个block
  2. blcok变量的初始化
  3. 简化block的定义
  4. 会在block内部访问与修改外部变量
  5. 会将block作为参数传递
  6. 知道block在哪

1.如何定义一个block?

1). block是1个数据类型,我们可以声明block类型的变量. block类型的变量中专门来存储1段代码的.
    这段代码可以返回值可以有参数.

2). block类型的变量,虽然是用来存储1段代码的.
    但是,1个block变量中并不是任意的1段代码都可以存储的.
    而是有限定的.
    
    在声明1个block类型的变量的时候 必须要指定这个block变量中可以存储的代码的参数和返回值描述.
    一旦指定,这个block变量中只能存储这样的代码段.别的格式的代码段是无法存储进去的.

3). 如何去声明block类型的变量.
    
    a. 根据刚刚的解释,声明block变量的时候,要指定这个这个block变量中存储的代码段的返回值和参数.

    b. 声明block变量的语法:

       返回值类型 (^block变量名称)(参数列表);

       void (^myBlock)(); 
       代表声明了1个block类型的变量,变量名加做myBlock.
       这个变量中只能存储没有返回值,也没有参数的1段代码.


       int (^myBlock)();
       代表声明了1个block类型的变量,变量名加做myBlock.
       这个变量中只能存储返回值为int类型的,没有参数的1段代码.

       int (^myBlock)(int num1,int num2);
       代表声明了1个block类型的变量,变量名加做myBlock.
       这个变量中只能存储返回值为int类型的,并且有两个整型的参数的1段代码.

    c. 特别注意:

       1个block变量中只能存储和这个block变量要求相同的1短代码.

2.block变量的初始化

1). 初始化block变量的原理: 写1段符合block变量要求的代码,把这段代码存储到这个block变量中.


2). 书写1个block代码段的语法格式.

    ^返回值类型(参数列表){
        代码;
    };


3). 无参数无返回值的代码段.

    ^void(){
        NSLog(@"我爱你");
        NSLog(@"打瞌睡的小女孩");
    };

    这个时候,就可以将这段代码 通过赋值符号. 赋值给无参数,无返回值的block变量.

     void (^myBlock1)();
     myBlock1 =  ^void(){
        NSLog(@"我爱你");
        NSLog(@"打瞌睡的小女孩");
     };

     代表的意义:myBlock1变量中存储了这段代码;


4). 有返回值无参数的代码段. 
    注意: 如果代码段标识了有返回值,那么在代码段结束之前,必须要使用return返回1个数据.

    ^int(){
       int num1 = 10;
       int num2 = 20;
       int num3 = num1 + num2;
       return num3;
    };


5). 有返回值有参数的代码段.

    ^int(int num1,int num2){
        int num3 = num1 + num2;
        return num3;
    };


6). 特别强调: block变量中只能存储和这个block变量要求相同的代码段.否则就会报语法错误.

3.简化block的定义

1). 感觉到隐隐不爽的地方: 声明1个block变量代码太长了.

2). 将长的block变量定义变得短一些.

3). typedef: 为1个已经存在的数据类型取1个别名.     
    当1个数据类型太长的时候,我们就可以使用typedef给它定义1个短别名,这样方便.

4). typedef也可以将1个长的block类型定义为1个短类型.

    语法格式: typedef 返回值类型 (^新类型名称)(参数列表);
    
    typedef void (^NewType)();
    代表新定义了1个类型 这个类型的名字叫做NewType.
    这是1个无参数无返回值的block类型.

    如果我们要定义1个无参数无返回值的block变量.直接使用NewType就可以定义了.


    typedef int (^NewType)(int num1,int num2);
    代表新定义了1个数据类型.  这个类型的名字叫做NewType.
    这是1个返回值为int 有两个整型参数的block类型.  
    如果我们要定义1个返回值为int 有两个整型参数的block类型变量. 直接使用这个新类型就可以定义.

4. 会在block内部访问与修改外部变量

1). 在block代码块的内部可以定义1个和外部的变量名称相同的变量.
    访问的时候,是就近原则.


2). 在block代码块的内部可以去取出外部的全局变量和局部变量的值.
    但是,在block代码块的内部,可以修改全局变量的值,但是不能修改外部的局部变量的值.


3). 如果就是希望在block代码块的内部去修改外部的局部变量的值.
    那么就给这个局部变量加个__block的修饰符.


4). block修改外部变量
    // 类型  变量名 = 值;
    __block int age = 100;
    NSLog(@"====%p",&age); // 栈
    // 使用__block修饰外部变量时, 在定义完成block之后,栈中的外部变量就是一个摆设,没有什么卵用了
    void (^block)() = ^{
        age = 200;
        NSLog(@"block中的age = %d",age); // 200
        NSLog(@"我是block = %p",&age); // 堆
    };
    NSLog(@"====%p",&age); // 栈
    NSLog(@"age = %d",age); // 100
    // 执行block
    block();
    NSLog(@"====%p",&age); // 堆
    NSLog(@"age = %d",age); // 200

5.将block作为参数传递

1). block是1个数据类型.
    那么block就必须可以作为方法/函数的参数.


2). 如何为函数写1个block类型的参数.

    1> 只需要在函数的小括弧中写声明1个block类型的变量就可以.

        void test(void (^block1)());
        代表,这个函数有1个block参数.无返回值无参数的block参数.


    2> 如果你觉得晕.
        那么就可以使用typedef将block类型定义的短1些.

        typedef void (^NewType)();
        void test(NewType b1)


3). 如何调用带block参数的函数.

    1> 如果调用的函数的参数是1个block类型的.
        那么要求传递1个和形参block类型相同的block变量

        可以先将符合要求的代码存储在1个block变量中,然后传递这个变量.


    2> 可以直接传递符合要求的代码段.


         test( ^{
             NSLog(@"啦啦啦啦啦,我是打瞌睡的小行家");
             NSLog(@"不等天明打瞌睡");
             NSLog(@"太阳出来还在打!");
         });


4. 把block作为函数的参数能够实现什么效果?

    之前的函数的参数能做什么事情: 可以将调用者的数据传递到函数的内部去使用.
    block作为参数: 可以将调用者的1段代码传递到函数的内部去执行.



5. 什么时候需要将block作为参数?

    1个函数代表1个相对对独立的功能.
    函数在完成这个功能的时候,发现需要执行1段代码才可以继续完成.
    而这段代码函数内部不确定是什么样的代码
    只有调用者确定.
    那么这个时候,就可以将block作为函数的参数.
    让调用者在调用这个函数的时候 把这段代码传递进来.
    放在这里执行.

6.知道block在哪

block有三种类型:
    1> 全局block:
    - 不管是ARC还是MRC,block内部没有访问任何外部变量或访问的外部变量是静态变量时,block就是全局block

    2> 堆block:
    - 在MRC下,给block调用copy方法,会将栈block拷贝到堆中.
    - 在MRC环境下,如果block是堆区block,需要程序猿手动release

    3> 栈block:
    - 在MRC环境下,block内部访问了外部变量时且不是静态变量,block就是栈block

最后分享一个关于block是如何实现的技术博客:谈Objective-C block的实现-唐巧

你可能感兴趣的:(iOS-block的演示)