Block 的語法

一直以來還是有不少人不滿 block 語法,甚至有人成立了一個叫做 fuckingblocksyntax.com 的網站。這個網站的網域名稱不怎麼優雅,不過裡頭倒是清楚整理了我們應該如何宣告 block。

將 block 宣告成變數(local variable)的語法是:

returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};

宣告成 Objective-C property 的語法是:

@property (nonatomic, copy) returnType (^blockName)(parameterTypes);

宣告成 method 的參數(method parameter)的語法是:

- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;

在執行某個需要傳入 block 當做參數的 method 的時候,則是用這以下方式呼叫。這也是絕大多數用 block 當做 callback 的處理方式:

[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];

把一種 block 宣告成 typedef:

typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};

Block 也可以當成 C function 的參數或是回傳結果的型別,但是,在這種狀況下,我們不能夠直接使用 returnType (^)(parameterTypes) 這種語法,必須要先宣告成 typedef 才行。也就是說,這樣會被當成不合法:

(void (^)(void)) test((void (^)(void)) block) {
    return block;
}

但可以寫成這樣:

typedef void (^TestBlock)(void);
TestBlock test(TestBlock block) {
    return block;
}

雖然 C function 的參數不能夠使用 returnType (^)(parameterTypes) 語法,但是一個 block 倒是可以使用這種語法撰寫輸入與回傳值的型別,但其實在這種狀況下,還是比較建議使用 typedef 宣告。比方說,我們現在要宣告一個 block,這個 block 會回傳另外一個型別為 int(^)(void) 的 block,就會寫成這樣:

int (^(^counter_maker)(void))(void) = ^ {
    __block int x = 0;
    return ^ {
        return ++x;
    };
};

可讀性實在非常差。不如寫成這樣:

typedef int (^CounterMakerBlock)(void);
CounterMakerBlock (^counter_maker)(void) = ^ {
    __block int x = 0;
    return ^ {
        return ++x;
    };
};

results matching ""

    No results matching ""