• 从C的声明符到Objective-C的Blocks语法


    原文链接:http://nilsou.com/blog/2013/08/21/objective-c-blocks-syntax/

    在这个post中,我先以C简单和内置复杂的声明开始,直到我们开始接触Objective-C的Blocks语法。当我接触block语法的时候也花了一段时间去理解,但是一旦你理解了block语法的结构和它的来源,那你下次用到block时,再也不要问Google大神啦。

    如果你希望你写block的时候手到擒来,那就继续读下去吧!

    申明

    C里面的变量都是用声明符声明的。

    声明有两个规则:

    1. 指定变量的类型(这是编译器希望在内存空间中找到的)
    2. 给变量一个名字让他对分配的空间可用(即给分配的空间取个名字)。

    让我们定义一个最基础的声明:

    1
    int a;

          这也许就是你曾经写过的C语言代码。

          int是基本类型,a是变量名或叫做标识符。

          当阅读一个声明的时候,你从标识符开始,一直向右看,然后重新从最左边的变量开始(我将在下一章解释为什么)。

          这里我们定义的变量右边没有东西,所以这只是简单的说明了:a是一个int类型的。

          一个声明只能有一个基本类型,并且类型必须放在声明的最左边。

          声明可以用修饰符修改基本类型来创建衍生类型。四个修饰符(三个来自ANSI-C,一个来自Apple’s proposed extension)分别为:*[ ],( )^

          三个ANSI-C修饰符

    指针修饰符 *

    1
    int *a;

          基本类型任然是int,变量名为a,但是指针修饰符*告诉我们a是一个指向int的指针而不是int。

          * 修饰符总是出现在被修饰变量的左边。

    数组修饰符 [ ]

    1
    int a [ ];

          这里数组修饰符[ ]告诉我们 a 现在是一个含有int的数组,而不是简单的int。比如int a[10];

          [ ]修饰符总是出现在被修饰变量的右边。

    方法修饰符 ( )

    1
    int f();

          方法修饰符 ( )告诉我们f是一个返回int类型的方法。这个修饰符也可以指定方法需要的参数,如:int f(long);是一个需要long类型作为变量,并且返回一个int类型的方法。

          ( )修饰符总是出现在被修饰变量的右边。

    组合修饰符

    指针和数组

          修饰符可以被组合起在一起来创建更复杂的变量类型。跟算法优先级一样(* 和/在+和-之前执行),修饰符也是有优先级的。[ ]( )*^有更高的优先级。既然两个拥有更高优先级的修饰符写到了变量右边,当阅读复合声明时,你需要从标识符开始,向右阅读,一旦你阅读到声明结束或者右括号时,再向左阅读。

    1
    int *a [];

          或者你也可以这样写增加阅读性:

    1
    int *(a[]);

          这是一个保存了指向int类型指针的数组。

          然后你可能想问,如果我想声明一个指向int类型数组的指针该怎么办?既然*比[]的优先级低,你需要使用圆括号来强制*修饰符有优先级。

    1
    int (*a)[];

          这便是一个指向int类型数组的指针。

    数组和方法

          你不可能定义一个包含方法的数组,并且方法不能返回数组或方法。然而方法可以获得数组作为参数。

    1
    int f (int [10]);

          这是一个方法,拥有一个含有10个int数组作为参数,并且返回一个int类型的值。

    指针和方法

    1
    2
    int *f();
    int *(f());

          在这两种情况一样,f是一个方法,这个方法返回一个指向int类型的指针。

          如果你想定义一个指向方法的指针该肿么办?圆括号!

    1
    int (*f)();

          f是一个指针,指向一个返回int类型的方法。

          block指针修饰符^

          Apple引进了第四个修饰符:^。这个修饰符叫做block指针修饰符(或者像最初那样叫做闭包修饰符)。blocks和指向方法的指针非常类似。你可以使用声明方法指针的方法来声明block。

          block指针修饰符只能被应用于方法(你不可以写int ^a;这是没有被定义的)。

          这正是为什么int ^b( )是非法的,并且会造成编译器错误:如果你使用优先级规则来读这个声明,b将会是一个方法,这个方法返回一个指向int类型的block指针。你也知道,并没有这回事儿。所以当你声明一个block时,你总是需要将标识符和修饰符放在圆括号中了。

    1
    int (^b)();

          b是一个block指针,这个指针指向返回int类型的方法。

          当然你也可以指定block所需要的参数:

    1
    int (^b)(long);

          是一个block,需要一个long类型作为参数,并且返回int。

          现在,你应该已经知道一些你需要记住的block语句的语法了:第一,是定义block的名字,另一个是要把block传递给Objective-C方法。

    抽象声明符

          声明符由两部分组成:一个你插入到标识符的抽象声明符。

          抽象声明符在标准C中被用在三种情况:

                  1.在 int *a; long *b = (long *) a; 中, (long *) 是一个指向long的抽象声明符

                  2.作为sizeof()的参数:malloc(sizeof(long *));

                  3.为方法声明参数类型时:int f(long *);

          Objective-C使用在多个地方使用抽象声明符:当为方法声明参数或者返回值时。

    1
    - (long **) methodWithArgument:(int *)a;

          这里long ** 和int *都是抽象声明符。

          所以为了在Objective-C方法中使用blocks作为参数或者返回值,我们需要寻找为那些blocks定义的抽象声明符。我们可以通过移去标识符。

          int (^b)( )变成int (^)( ),  int (^b)(long)变成 int (^)(long).

    例如:

    1
    2
    - (void) methodWithArgument: (int(^)( )) block;
    - (void) anotherMethodWithArgument: (void(^)(long arg1)) block;

          然而在这些抽象声明中你不需要为你的block参数取名,这是一个很好的主意。当block期望作为参数时,这将是一个很好的暗示,并且当使用这种方法时Xcode是完全自动的。

    Block 字面意思

          当你写 int a = 2;,int a是一个声明,2是int的字面意思。

          ^也被用作为一元运算符来改造一个方法实现为block。你不需要指定block返回类型。

          既然这是block的实现,你需要在这里面定义你的参数。

          对于block  int (^block)(long, long);来说,它的字面意思可能会是:

    1
    2
    3
    4
    5
    block = ^(long a, long b)
    {
        int c = a + b;
        return c;
    }

    结论

          尽管看起来有点复杂,Objective-C中的blocks语法是依赖于标准C语法的。Objective-C中的block只不过是一个捕获函数范围的指针。一旦你理解这些概念,并且不断练习读写一些blocks声明,你将会发现blocks很好理解。

  • 相关阅读:
    Python脚本模拟登陆DVWA
    PHP单元测试使用
    PHPUnit实践一(初识)
    composer引用本地git做为源库
    编写自己的composer项目
    Laravel 核心--Facades 门面
    Laravel5 创建自定义门面(Facade)
    简单理解laravel框架中的服务容器,服务提供者以及怎样调用服务
    Laravel自带SMTP邮件组件实现发送邮件(QQ、163、企业邮箱都可)
    cocos2d-x游戏开发系列教程-坦克大战游戏之坦克和地图碰撞的检测下
  • 原文地址:https://www.cnblogs.com/yingkong1987/p/3315092.html
Copyright © 2020-2023  润新知