Objective-C 的 block 語法看起來比較複雜,其實它只是一個簡單的擴展。下面咱們從 C 的聲明符開始,一步一步地引入 block 概念。objective-c
首先複習一下 C 的聲明符:segmentfault
int a
int
指定了類型,a
是變量的名稱。數組
聲明符可使用修飾符,C 有三種修飾符:*
、[]
、()
。閉包
int *a
a
是指向int
的一個指針。函數
int a[]
a
是一個由int
組成的數組。spa
int f()
f
是一個返回int
的函數。指針
這些修飾符能夠混合使用。混合時,從變量名稱開始往右讀,讀到盡頭或閉括號以後再從變量名稱開始往左讀。code
例如:blog
int *a[]
先往右讀,[]
是有一個數組,再往左讀int *
是指向int
的指針。因此int *a[]
就是由指向int
的指針組成的數組,等價於int *(a[])
。ci
再如:
int (*a)[]
先由a
往右讀,碰到)
,所以再往左讀,讀到*
,所以是一個指針。而後再往右讀[]
,再往左讀int
。因此最後int (*a)[]
是指向由int
組成的數組的指針。
同理,int *f()
,是一個函數,返回一個指向int
的指針。而int (*f)()
則是一個指針,指向一個返回int
的函數。
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 = ^(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