Block 使用方式由淺入深

Objective-C 語言一直以來由蘋果公司維護著,為其增加了不少更加現代化的語法,其中 block (其他語言一般都稱閉包)語法就是在 iOS 4 發布的,與此同時還提供了抽象程度極高的GCD 技術,用于簡化線程的操作!所以今天說的 block 并不是新的技術,但它恐怕是最難記憶的的語法了,并且使用形式很是靈活,因此總結一下我平時使用的幾種類型,供大家參考。

特為此寫了個 demo 來幫助理解。

1.描述為屬性

這是最為常見的用法了,一般都是先賦值,當觸發某個邏輯時進行回調;

@property (nonatomic, copy) returnType (^blockName)(parameterTypes);
self.blockName = ...;//賦值一個block
self.blcokName(parameters);//調用

2.作為形參(parameter),做回調

a.經常和屬性配合使用;一般場景是方法內部有異步執行的任務,執行完畢后通過這個block參數回調到調用處;

 - (void)doSomeThingWithCompletion:(retunType (^)(parameterTypes))blockName{
    async(...{
        blockName(parameters);
    });
 }

b.相當于寫個 setter 方法,給 block 屬性賦值,直接給屬性賦值的話需要手寫實現 block ,不容易記,這其實是為了方便調用者而已。

 - (void)registerXXXHandler:(void (^)(float))handler
{
    self.xxxHandler = handler;
}

3.作為實參(argument),實現block

調用一個帶有 block 參數的方法時,就需要實現這個 block 了,其實這個不用手寫,IDE 會提示的,直接回車即可;

[self doSomeThingWithCompletion: ^retunType(parameters){
//...
}];

4. typedef 出"新類型"

以上使用一點也不友好,所以基本上我們都會使用 typedef 定義一個類型出來;

typedef returnType(^ TypeName)(parameterTypes) 
//以上用法可改為:
@property (nonatomic, copy) TypeName blockName;
- (void)doSomeThingWithCompletion:(TypeName)blockName;

5.方法內部當局部變量使用

如果一段代碼里有很多個 if else 分支,某些分支的處理完全一樣時,可將他們封裝到一個block塊里面;可以省去寫相同代碼的麻煩,也不必開辟一個新的方法;

 returnType (^blcokNmae)(parameterTypes) = ^returnType(parameters){ ... };
 //調用:
 returnType result = blcokNmae(parameters);

6.方法返回值

這種情況不太多,比如可用于實現鏈式編程;

//聲明
- (returnType (^) parameterTypes) method;
//實現
- (returnType (^) parameterTypes) method{
    return ^ returnType (parameters){
        //...
        return obj;//obj 是 returnType 類型
    };
}

舉個例子:

///設置url
- (SLNetworkRequest *(^)(NSString *url))c_URL;

- (SLNetworkRequest *(^)(NSString *url))c_URL
{
    return ^ SLNetworkRequest * (NSString *url){
        self.urlString = url;
        return self;
    };
}

7.高階 Block : 作為另一個Block的參數

這種情況用的不是太多,但是一旦有需要雙向交互的場景時,優勢就很明顯了!具體可看 demo 實現的 3G 網絡詢問用戶是否下載的場景:

typedef returnType(^ Block1)(parameterTypes) 
typedef returnType(^ Block2)(parameterTypes, Block1) //Block1作為Block2的參數部分

可實現雙向通信,比如:

- (void)doSomeThingWithCompletion:(Block2)blockName
{
    async(...{
         Block1 block1 = ^(isOk){
             if(isOK){
                //start download...
            }else{
                //cancel something...
            }
         };
         blockName(parameters, block1);
    });
}

調用:
[self doSomeThingWithCompletion: ^ returnType(parameters, block1){
    //內部處理完畢后,回調到此;
    //根據結果(parameters)做相應的邏輯,然后將處理結果再次回調到方法內部
    if(parameters){
        block1(NO);//通過block1再次回調回去告知可以進行下一步了
    }else{
        block1(YES);//通過block1再次回調回去告知不能繼續
    }
}];

最近我制定了 H5-Native 的交互方案,編寫交互需要注入的 js 腳本,通信 API 也是雙向的,其原理就是 block (閉包)的嵌套使用;API 出來后 H5 和 Native 的開發同事們都很 Happy 呢!

如果你有其他有趣的使用方法,請提供給我吧!

前五個算是翻譯,不過也確實是工作中經常用的,原文地址 : http://fuckingblocksyntax.com

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容