Fork me on GitHub

OC基础学习12:代码块(Block)

代码块(Block)/闭包(closure) 是对C语言中函数的扩展。
代码块两种类的绑定:
自动绑定(automatic binding) 栈内存
托管绑定(managed binding) 堆内存

  • 代码块和函数指针
    函数指针的声明:
    void (*my_func)(void);
    *变成^(幂符号)变成代码块定义:
    void (^my_block)(void);

    代码块展示:

    1
    2
    3
    int (^square_block)(int number) = ^(int number) {return (number * number);};
    int result = square_block(5);
    printf("Result = %d\n", result);

    等号前面是代码块的定义,而等号后面是实现内容。一般形式:

    1
    <returntype> (^blockname)(list of arguments) = ^(arguments){ body; };

    没有参数时可以简写:

    1
    void (^theBlock)(void) = ^{ printf("Hello Blocks!\n"); };
  • 使用代码块
    代码块可以访问与它相同的(本地)有效范围内声明的变量。

    1
    2
    3
    4
    5
    int value = 6;
    int (^multiply_block)(int number) = ^(int number) { return (value * number);};
    value = 8;
    int result2 = multiply_block(7);
    printf("Result2 = %d\n", result2); // 是6*7,不是8*7
  • 直接使用代码块

    1
    2
    3
    4
    5
    6
    NSArray *array = [NSArray arrayWithObjects:@"Amir", @"Mishal", @"Irrum", @"Adam", nil];
    NSLog(@"Unsorted Array %@", array);
    NSArray *sorteArray = [array sortedArrayUsingComparator:^(NSString *objet1, NSString *object2) {
    return [objet1 compare:object2];
    }];
    NSLog(@"Sorted Array %@", sorteArray);
  • 使用typedef关键字

    1
    2
    3
    4
    5
    typedef double (^MKSampleMultiply2BlockRef)(double c, double d);
    MKSampleMultiply2BlockRef multiply2 = ^(double c, double d) { return c * d; };
    printf("%f, %f", multiply2(4, 5), multiply2(5,3));
    typedef void (^MKSampleVoidBlockRef)(void);
    typedef void (^MKSampleStringBlockRef)(NSString *);
  • 代码块和变量
    代码块被声明后会捕捉创建点时的状态。
    代码块可以访问函数用到的标准类的变量:

    • 全局变量,包括封闭范围内声明的本地静态变量。
    • 全局函数
    • 封闭范围内的参数
    • 函数级别(即与代码块声明时相同的级别)的_block变量。
    • 封闭范围内的非静态变量会被获取为常量。
    • Objective-C的实例变量
    • 代码块内部的本地变量
  • 本地变量

    1
    2
    3
    4
    5
    6
    7
    8
    typedef double (^MKSampleMultiplyBlockRef)(void);

    double a = 10, b = 20;
    MKSampleMultiplyBlockRef multiply = ^(void){ return a * b; };
    NSLog(@"%f", multiply()); // 200.0
    a = 20;
    b = 50;
    NSLog(@"%f", multiply()); // 200.0
  • 全局变量

    1
    2
    3
    4
    5
    6
    7
    typedef double (^MKSampleMultiplyBlockRef)(void);

    static double a = 10, b = 20;
    MKSampleMultiplyBlockRef multiply = ^(void){ return a * b; };
    NSLog(@"%f", multiply()); // 200.0
    a = 20; b = 50;
    NSLog(@"%f", multiply()); // 1000.0
  • 参数变量
    代码块中的参数变量与函数中的参数变量具有同样的作用。

    1
    2
    3
    typedef double (^MKSampleMultiply2BlockRef)(double c, double d);
    MKSampleMultiply2BlockRef multiply2 = ^(double c, double d) { return c * d; };
    printf("%f, %f", multiply2(4, 5), multiply2(5,3));
  • __block变量
    本地变量会被代码块作为常量获取到。在代码块中修改会报错。

    1
    2
    3
    double c = 3;
    MKSampleMultiplyBlockRef multiply = ^(void) { c = 5; return c; };
    //报错: Variable is not assignable (missing __block type specifier)

    将本地变量标记为__block,就可以修改了

    1
    2
    __block double c = 3;
    MKSampleMultiplyBlockRef multiply = ^(void) { c = 5; return c; };
  • 代码块内部的本地变量

坚持原创技术分享,您的支持将鼓励我继续创作!
  • 本文标题: OC基础学习12:代码块(Block)
  • 本文作者: AndyRon
  • 发布时间: 2017年09月12日 - 21:13
  • 最后更新: 2017年10月08日 - 14:27
  • 本文链接: http://andyron.com/2017/oc-basic-12.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!