iOS的鏈式開發

derek發表於2019-01-25

前言

我們開發過程當中很多時候會對一個物件的屬性多次設定引數,比如設定一個UILable和UIButton時候,會多次使用點語法setter和getter屬性,步驟繁瑣,於是我就想起了SDAutoLayoutMasonry當中使用的鏈式程式設計結構,而且現在很多的比較成熟的第三方框架也越來越多的使用這種開發方式。

這種程式設計方式最大的優點就是一次開發,後面使用都是迅速呼叫,省去繁瑣的多次呼叫點語法,但也有缺點,初次開發程式碼量較大,語法複雜。但是對於常用的一些類來說基本是一次開發終生受益。

使用方法

Masonry的使用方法

SDAutoLayout的使用方法

實現原理

通過上面兩個例子,我們嘗試推測一下大概的結構:

  1. 鏈式語法每一次呼叫都會呼叫點語法
  2. 又因為通常情況下在OC呼叫方法當中,一般使用中括號來呼叫,所以可以推測呼叫的是Block
  3. 又因為鏈式程式設計的語法是連續呼叫,並且很多時候是無序的連續呼叫方法,所以我們能推測出,每次呼叫返回的應該是這個類的例項物件

我們先看看上面兩個的實現原理

Masonry

- (MASConstraint * (^)(CGFloat))offset {
     return ^id(CGFloat offset){
         self.offset = offset;
         return self;
     };
 }複製程式碼

SDAutoLayout

typedef SDAutoLayoutModel *(^MarginToView)(id viewOrViewsArray, CGFloat value);//getter方法的返回值

 - (MarginToView)leftSpaceToView
 {
     if (!_leftSpaceToView) {
         _leftSpaceToView = [self marginToViewblockWithKey:@"left"];
     }
     return _leftSpaceToView;
 }

 - (MarginToView)marginToViewblockWithKey:(NSString *)key
 {
     __weak typeof(self) weakSelf = self;
     return ^(id viewOrViewsArray, CGFloat value) {
     SDAutoLayoutModelItem *item = [SDAutoLayoutModelItem new];
     item.value = @(value);
     if ([viewOrViewsArray isKindOfClass:[UIView class]]) {
         item.refView = viewOrViewsArray;
     } else if ([viewOrViewsArray isKindOfClass:[NSArray class]]) {
         item.refViewsArray = [viewOrViewsArray copy];
     }
     [weakSelf setValue:item forKey:key];
     return weakSelf;
   };
 }複製程式碼

通過以上我們可以看出,基本和我們之前推測的是一樣的:使用點語法、運用Block回撥、返回值是呼叫的例項物件。

我們簡單分析一下

Masonry的方法做例子

- (MASConstraint * (^)(CGFloat))offset {
     return ^id(CGFloat offset){
         self.offset = offset;
         return self;
     };
}複製程式碼

以上方法可以看做作為一個getter方法,因為在我們使用點語法的過程當中,這個方法必須是有返回引數,但是無傳入引數,所以這個方法正好可以看做是offset這個屬性的getter方法來使用,也就是說可以直接用點語法來呼叫。

應該會有人來發問,offset的引數是怎麼傳進來的?
.offset(5)當中,(5)是整個Block的引數,並且也是作為Block的引數傳出去,因為BLock的返回值引數用於從外向內返回引數傳遞結果,這就是為什麼我們從外面傳入引數,在內部會得到引數數值的原因。

返回的引數是一個Block,MASConstraint是Block返回值的型別,CGFloat是Block返回引數的型別。以上都是Block的基礎用法,要是看的不是很明白,可以看一下我下面的參考檔案。

我們分析一下呼叫過程

  1. make.left.offset 得到的是一個Block
  2. make.left.offset(5) 傳入引數之後,執行Block,返回值為MASConstraint的物件,所以之後仍然可以繼續呼叫其他MASConstraint的方法。

使用場景

我覺得使用場景其實很多,看個人需求了,但是我總結的不外乎以下幾點:

  1. 需要取得返回值之後不斷的進行下一步運算,比如加減乘除計算器。
  2. 需要連續設定一個例項的引數,比如設定UILable的屬性等,不再需要連篇累牘的多次書寫點語法來設定屬性。

但是以上總結起來,其實就是需要對一個物件進行連續且重複操作的是時候需要使用鏈式程式設計的語法。

參考推薦專案

參考

另外

相關文章