iOS-block的妙用:鏈式編程(經(jīng)典應用:Masonry)

iOS開發(fā)當中有一個很特殊的存在,這個特殊就是block。在OC當中實現(xiàn)某一個功能都是一個響應對象調(diào)用一個響應方法,簡而言之就是Target-Action。

以UIButton為例:

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];

UIButton的事件就是一個響應對象和一個響應方法之間的一一映射。

與UIButton這種不同,block則不一樣,其根本不需要響應對象,如下:

    void (^LogString)(NSString *string) = ^(NSString *string) {
        NSLog(@"這是一個用來打印log的block,需要打印的字符串為:%@", string);
    };
    
    LogString(@"12345");

block的使用無非是以下三個步驟:

1.block的聲明。上述代碼中的void (^LogString)(NSString *string就是將void (^)(NSString *string)聲明成一個叫LogString的block
2.block的實現(xiàn)。上述代碼中'='后面的便是block的實現(xiàn),包含了參數(shù)與返回值
3.block的調(diào)用。上述代碼中的LogString(@"12345")就是對block的調(diào)用

今天小編就來說說block的另外一項應用:鏈式編程。

說到鏈式編程最經(jīng)典的應用便是Masonry了,以下便是Masonry的簡單代碼:

    [self.nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.top.equalTo(view).priorityHigh();
    }];

其中可以看到對于make這個MASConstraintMaker對象的設置是以一系列的點語法來實現(xiàn)的。

當然,這個leadingtop也是很容易實現(xiàn)的,無非就是以系列的get方法而已。但是后面的equalTo(view)priorityHigh()是什么鬼?我們點進去:

Masonry源碼

這個時候可以看到equalTo方法的返回值是一個block,而equalTo里面則是一個block的聲明,并且將這個block給return了。

如此我們在調(diào)用equalTo(view)的時候經(jīng)歷了以下步驟:

1.調(diào)用equalTo方法的對象是MASConstraint,equalTo方法里面聲明了一個block和block的實現(xiàn)
2.MASConstraint對象調(diào)用equalTo方法實際上是返回了一個block,這個block的返回值還是MASConstraint對象
3.步驟2獲取到一個block,這個block參數(shù)是一個id類型的數(shù)據(jù),那么equalTo后面的view參數(shù)實際上就作為block的參數(shù)了,這也就實現(xiàn)了一個block的調(diào)用
4.因為block的返回值是MASConstraint對象,所以經(jīng)歷步驟3之后的值實際上還是MASConstraint,調(diào)用priorityHigh()就又回到了步驟1

說來說去是不是繞糊涂了?實際上這無非就是block的聲明,block的實現(xiàn)與block的實現(xiàn)這三個步驟的另外一種變體。

接下來我們依據(jù)上面總結(jié)的Masonry的步驟來對UILabel實現(xiàn)鏈式編程:

1.聲明一個UILabel的分類,如下:

UILabel的分類

2.初始化UILabel的方法聲明。在UILabel+Additions.h里聲明一個叫l(wèi)abel的方法,這個方法沒有參數(shù),返回值是一個block,這個block的返回值是一個UILabel對象,block的參數(shù)是CGRect的結(jié)構(gòu)體。

/**
  * 初始化label,此方法是類方法且沒有參數(shù)
  * 此方法的返回值是一個block
  * 這個block參數(shù)為一個CGRect的參數(shù)
  * 返回值還是UILabel對象,用來實現(xiàn)鏈式編程
 */
+ (UILabel *(^)(CGRect frame))label;

3.初始化UILabel的方法實現(xiàn)。在UILabel+Additions.m實現(xiàn)label方法,最主要是實現(xiàn)block,這個在block里實現(xiàn)UILabel的創(chuàng)建,并將這個block返回,如下:

+ (UILabel * _Nonnull (^)(CGRect))label {
    // 聲明并實現(xiàn)一個block,并返回
    return ^(CGRect frame) {
        // 根據(jù)傳過來的frame參數(shù)初始化UILabel,并返回
        return [[UILabel alloc] initWithFrame:frame];
    };
}

同理,設置UILabel的text和textColor也是如此,以下便是代碼:
UILabel+Additions.h進行方法的聲明:

// 對象方法
- (UILabel *(^)(NSString *title))title;
- (UILabel *(^)(UIColor *titleColor))titleColor;

UILabel+Additions.m對方法進行實現(xiàn):

- (UILabel * _Nonnull (^)(NSString * _Nonnull))title {
    return ^(NSString *title) {
        self.text = title;
        // 返回self就可以了
        return self;
    };
}

- (UILabel * _Nonnull (^)(UIColor * _Nonnull))titleColor {
    return ^(UIColor *titleColor) {
        self.textColor = titleColor;
        // 返回self就可以了
        return self;
    };
}

應用代碼:

    UILabel *label = UILabel.label(CGRectMake(100, 100, 200, 50)).
                     title(@"鏈式編程的應用").
                     titleColor([UIColor greenColor]);
    label.backgroundColor = [UIColor redColor];
    [self.view addSubview:label];

效果:


效果圖

最后打個廣告,個人第三方庫:
UDUserDefaultsModel:NSUserDefaults的改進方案
YIIFMDB:直接操作Model進行增刪改查,數(shù)學運算等,且sql語句易于管理

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容