iOS 編程思想 -- MAS&鏈式編程

前言

編程思想在iOS的應用中大概有那麼幾類,咱們最經常使用的當屬於面向對象的編程思想,一切皆對象,基於這種思想離不開的就是咱們最經常使用的封裝、繼承、多態。平時工做中咱們也會接觸一些面向協議的編程思想,好比說接口分離解耦合,再好比說咱們最經常使用的delegate都是面向協議的思想,還有就是基於ReactiveCocoa框架也就是平時聽到的RAC提供的響應式編程思想,今天主要分析下另外一種編程思想,鏈式編程。編程

首先簡單分析一下Masonry的實現過程:

Masonry框架做爲iOS開發者耳熟能詳,你們在作純代碼適配的時候應該都曾用過,下面就以Masonry爲例,但本文不過多的分析MAS源碼,旨在提煉思想。數組

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];
}

- (id)initWithView:(MAS_VIEW *)view {
    self = [super init];
    if (!self) return nil;
    self.view = view;
    self.constraints = NSMutableArray.new;
    return self;
}
複製代碼
  • 1.建立約束製造者MASConstraintMaker而且綁定控件,在約束製造者init的同時生成了一個保存全部約束的數組constraintsbash

  • 2.執行mas_makeConstraints傳入的block,返回咱們剛纔建立的約束製造者constraintMaker框架

  • 3.讓約束製造者安裝約束,執行install方法。函數

咱們再看一下install裏面作了什麼:

- (NSArray *)install {
    if (self.removeExisting) {
        NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
        for (MASConstraint *constraint in installedConstraints) {
            [constraint uninstall];
        }
    }
    NSArray *constraints = self.constraints.copy;
    for (MASConstraint *constraint in constraints) {
        constraint.updateExisting = self.updateExisting;
        [constraint install];
    }
    [self.constraints removeAllObjects];
    return constraints;
}
複製代碼

其實是遍歷了咱們建立約束製造者constraintMaker時所建立的constraintsconstraints裏面實際上存儲的是咱們爲控件添加的全部約束信息,而後分別對每條約束之行install。那麼問題來了,constraints裏面的約束從哪裏來的呢。這就要回到了上面說的第2步,block將約束製造者返回給用戶,讓用戶經過constraintMaker去設置控件的約束,這些約束實際上就是存儲到了constraints中。當執行第3return [constraintMaker install];的時候,就是將全部調用者添加的佈局轉換爲NSLayoutConstraint對象也就是咱們熟悉的純代碼適配,進行佈局更新。佈局

爲何要先研究Masonry呢

實際上Masonry就是基於鏈式編程思想實現的開源框架,即強大,又直觀。好比說咱們在使用Masonry的時候一般會這樣寫:ui

[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.height.top.mas_equalTo(44);
    make.left.mas_equalTo(5);
    make.centerY.equalTo(self);
}];
複製代碼

爲何make能夠一直這麼點下去,點語法給咱們的第一感受是get方法,實際上確實是get方法:spa

- (MASConstraint *)height {
    return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];
}
複製代碼

經過源碼能夠看到.height實際上返回的並非一個int或者NSInteger類型變量,而是MASConstraint,是約束製造者自己,實際上每次調用.height就是將約束添加到咱們上面提到的constraints數組中。到這裏,鏈式編程的特色就顯而易見了,那就是方法返回值必需要有方法的調用者。那麼還有疑問,mas_equalTo()是什麼鬼。下面着重講一下.mas_equalTo()code

仍是經過源代碼點進去看一下:對象

- (MASConstraint * (^)(id))equalTo {
    return ^id(id attribute) {
        return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}
複製代碼

返回值是一個MASConstraint * (^)(id)block類型,到這裏咱們瞭解了.mas_equalTo其實是返回了一個返回值爲MASConstraint類型的block,當咱們外面調用block的時候實際上執行的是self.equalToWithRelation(attribute,NSLayoutRelationEqual);函數,沒錯,它返回的依舊是MASConstraint類型,依舊是方法的調用者,也就是前面提到的約束製造者,因此咱們在調用mas_equalTo()以後還能繼續點下去,像不像個無底洞。若是這樣很差理解的話咱們能夠將添加約束的源碼改寫一下來實現:

[view mas_makeConstraints:^(MASConstraintMaker *make) {
//     make.height.top.mas_equalTo(44);
    MASConstraint * (^)(id)block = make.height.top.mas_equlTo;
    MASConstraint *make = block(44);
    make.top...
}];
複製代碼

這下應該就很好理解了。

最後總結一下什麼是鏈式編程,一句話就是方法返回值必需要有方法的調用者!

相關文章
相關標籤/搜索