Objective-C 的 block 语法看起来比较复杂,其实它只是一个简单的扩展。下面我们从 C 的声明符开始,一步一步地引入 block 概念。
声明符
首先复习一下 C 的声明符:
int a
int
指定了类型,a
是变量的名称。
声明符可以使用修饰符,C 有三种修饰符:*
、[]
、()
。
指针
int *a
a
是指向int
的一个指针。
数组
int a[]
a
是一个由int
组成的数组。
函数
int f()
f
是一个返回int
的函数。
混合
这些修饰符可以混合使用。混合时,从变量名称开始往右读,读到尽头或闭括号之后再从变量名称开始往左读。
例如:
int *a[]
先往右读,[]
是有一个数组,再往左读int *
是指向int
的指针。所以int *a[]
就是由指向int
的指针组成的数组,等价于int *(a[])
。
再如:
int (*a)[]
先由a
往右读,碰到)
,因此再往左读,读到*
,因此是一个指针。然后再往右读[]
,再往左读int
。所以最后int (*a)[]
是指向由int
组成的数组的指针。
同理,int *f()
,是一个函数,返回一个指向int
的指针。而int (*f)()
则是一个指针,指向一个返回int
的函数。
block 修饰符
Apple 在上述三个修饰符的基础上增加了一个修饰符,block 修饰符^
.
block 修饰符和指向函数的指针非常相似。上面我们提到int (*f)()
是一个指向返回int
函数的指针,类似地,int (^b)()
是一个指向返回int
函数的 block 指针,简称返回int
的 block。
因为 block 总是指向函数的,所以int ^a
和int ^b()
都是非法的,因为不存在指向int
的 block。
block 和指向函数的指针的区别在于,block 创建了一个闭包。
抽象声明符
将声明符中的变量名称去除后,我们就得到了抽象声明符。在 C 中,抽象声明符用于以下三种情形:
- 映射。
int *a; long *b = (long *) a;
。 -
sizeof()
的参数。malloc(sizeof(long *));
- 声明函数的参数。
int f(long *);
Objective-C 扩展了抽象声明符的用法:用于声明方法的参数和返回值。
- (long **)methodWithArgument:(int *)a;
同样适用于 block 声明符:
- (void)methodWithArgument:(int(^)())block;
- (void)anotherMethodWithArgument:(void(^)(long arg1))block;
block 字面量
^
除了作为修饰符使用之外,还可以作为操作符使用,将函数转化为 block。
block = ^(long a, long b) {
int c = a + b;
return c;
}
注意我们这里省略了 block 的返回值的类型声明,因为 Objective-C 会从return
语句中推导出类型。
总结
Objective-C 的 block 语法是在 C 的标准语法基础上的扩展。Objective-C 中的 block 不过是一个创建了闭包的指向函数的指针。
原文 From C Declarators to Objective-C Blocks Syntax
编译 SegmentFault
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。