iOS學習——佈局利器Masonry框架源碼深度剖析

  iOS開發過程當中很大一部份內容就是界面佈局和跳轉,iOS的佈局方式也經歷了 顯式座標定位方式 --> autoresizingMask --> iOS 6.0推出的自動佈局(Auto Layout)的逐步優化,至於爲何推出自動佈局,確定是由於以前的方法很差用(哈哈 簡直是廢話),具體如何很差用以及怎麼變化你們能夠瞅瞅 這篇文章iOS6.0推出的自動佈局實際上用佈局約束(Layout Constraint)來實現,經過佈局約束(Layout Constraint)能夠肯定兩個視圖之間精確的位置的相對距離,爲此,iOS6.0推出了NSLayoutConstraint來定義約束,使用方法以下:html

[NSLayoutConstraint constraintWithItem:view1
  attribute:NSLayoutAttributeLeft
  relatedBy:NSLayoutRelationEqual
  toItem:view2
  attribute:NSLayoutAttributeRight
  multiplier:1
  constant:10];

//翻譯過來就是:view1的左側,在,view2的右側,再多10個點,的地方。

佈局約束的添加規則:ios

(1)對於兩個同層級 view 之間的約束關係,添加到它們的父 view 上
(2)對於兩個不一樣層級 view 之間的約束關係,添加到他們最近的共同父 view 上
(3)對於有層次關係的兩個 view 之間的約束關係,添加到層次較高的父 view 上
(4)對於好比長寬之類的,只做用在該 view 本身身上的話,添加到該 view 本身上
數組

  具體關於NSLayoutConstraint的詳細使用方法參見:NSLayoutConstraint-代碼實現自動佈局。今天咱們文章的主角——Masonry框架其實是在NSLayoutConstraint的基礎上進行封裝的,這一點在後面的源碼分析中咱們詳細解釋。架構

1 Masonry的佈局教程

  當我們須要對控件的top,bottom,left,right進行約束就特別麻煩,在OC中有一個庫MasonryNSLayoutConstraint進行了封裝,簡化了約添加約束的方式和流程。用Masonry框架進行佈局很是簡單,主要特色是採用鏈式語法進行佈局,這一點使得咱們在使用和代碼佈局上更爲方便,利用Masonry進行佈局的前提條件之一是 佈局視圖必須先被添加到父視圖中簡單示例以下代碼,關於Masonry框架的使用並非本文的重點,詳情能夠參見:Masonry介紹與使用實踐:快速上手Autolayout。若是你的項目是Swift語言的,那麼就得使用SnapKit佈局框架了,SnapKit其實就是Masonry的Swift版本,二者雖然實現語言不一樣,可是實現思路大致一致。框架

UIView *sv1 = [UIView new];
//利用Masonry進行佈局的前提條件之一是 佈局視圖必須先被添加到父視圖中
[sv addSubview:sv1];
[sv1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
     
    /* 等價於
    make.top.equalTo(sv).with.offset(10);
    make.left.equalTo(sv).with.offset(10);
    make.bottom.equalTo(sv).with.offset(-10);
    make.right.equalTo(sv).with.offset(-10);
    */
     
    /* 也等價於
    make.top.left.bottom.and.right.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
    */
}];

 2 Masonry框架源碼分析

  Masonry框架是在NSLayoutConstraint的基礎上進行封裝的,其涉及到的內容也是很是繁多。在進行源碼剖析時咱們從咱們常常用到的部分出發,一層一層進行解析和研究。ide

2.1 調用流程分析

  首先,咱們先大致瞭解一下調用 mas_makeConstraints 進行佈局時的流程步驟,其實另外兩個 mas_updateConstraints 和 mas_remakeConstraints 的流程也基本上是同樣的。函數

  •  - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block 是Masonry框架中UIview + MASAdditionsUIview分類)中的方法,因此通常的控件視圖均可以直接調用該方法,該方法傳入一個block函數做爲參數(返回值爲void,參數爲MASContraintMaker的實例對象make)
  • 主要佈局方法 - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block 的源碼和解析以下,主要工做是建立一個約束建立器,並將其傳到block中(其實就是block中的make建立器)進行建立約束並返回
    @implementation MAS_VIEW (MASAdditions)
    
    - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
        //關閉AutoresizingMask的佈局方法是咱們進行Auto Layout佈局的前提步驟
        self.translatesAutoresizingMaskIntoConstraints = NO;
        //建立一個約束建立器
        MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
        //在block中配置constraintMaker對象,即將constraintMaker傳入block中(其實就是咱們在block中用來添加約束的make)進行約束配置
        block(constraintMaker);
        //約束安裝並以數組形式返回
        return [constraintMaker install];
    }
    
    ...
  • 約束安裝方法 [constraintMaker install]; 的源代碼以下,這部分的代碼很簡單,主要就是對當前約束建立器中的約束進行更新,由於除了咱們這個 mas_makeConstraints 方法中會調用該方法以外, mas_updateConstraints 和 mas_remakeConstraints 中都會調用該方法進行約束的安裝,因此在該約束安裝方法中考慮了約束的刪除和是否有更新等狀況的處理。工具

    //install方法主要就是對下面這個約束數組進行維護
    @property (nonatomic, strong) NSMutableArray *constraints;
    
    - (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;
    }
  • 上面這段代碼中真正添加約束的方法實際上是 [constraint install]; ,這裏咱們要分析一下這個install到底調用的是哪一個方法的install?由於這裏有好幾個類(MASConstraint、MASViewConstraint、MASCompositeConstraint)有install方法。要知道具體調用的是哪個類的install方法,咱們就要弄清楚這裏的約束constraint究竟是什麼類型,這就須要咱們瞭解約束建立器(MASConstraintMaker)中的約束數組constraints中添加的究竟是什麼類型的約束,通過分析(分析過程在後面會講到)咱們發現這裏添加的約束是MASViewConstraint類型的,根據面向對象的多態特性,因此咱們這裏調用的其實就是MASViewConstraint的install方法,該方法關鍵代碼(代碼太長,只放關鍵性代碼)以下,咱們能夠看到其實就是經過iOS系統自帶的自動佈局約束佈局類NSLayoutConstraint進行佈局
    - (void)install {
        if (self.hasBeenInstalled) {
            return;
        }
    
        ...
    
        //MASLayoutConstraint其實就是在NSLayoutConstraint基礎上添加了一個屬性而已
        //@interface MASLayoutConstraint : NSLayoutConstraint
        
        MASLayoutConstraint *layoutConstraint
            = [MASLayoutConstraint constraintWithItem:firstLayoutItem
                                            attribute:firstLayoutAttribute
                                            relatedBy:self.layoutRelation
                                               toItem:secondLayoutItem
                                            attribute:secondLayoutAttribute
                                           multiplier:self.layoutMultiplier
                                             constant:self.layoutConstant];
        layoutConstraint.priority = self.layoutPriority;
        layoutConstraint.mas_key = self.mas_key;
        
        ...
    
        //添加約束
        if (existingConstraint) {
            // just update the constant
            existingConstraint.constant = layoutConstraint.constant;
            self.layoutConstraint = existingConstraint;
        } else {
            [self.installedView addConstraint:layoutConstraint];
            self.layoutConstraint = layoutConstraint;
            [firstLayoutItem.mas_installedConstraints addObject:self];
        }
    }

   經過上面的分析和研究,咱們基本上已經把Masonry框架中主要佈局方法的主流程瞭解清楚了。由於這是第一次學習iOS第三方框架的源碼,在這個學習過程當中也走了不少彎路,最開始是從最基本的類開始看,後來發現越看越不懂,不知道這個屬性的定義在何時用到,是什麼含義((ノへ ̄、)捂臉。。。)。後來經過摸索才知道源碼學習應該直接從用到的方法着手,而後一步一步深刻分析源碼中每一步的目的和意義,順藤摸瓜,逐個擊破源碼分析

 2.2 Masonry框架中的鏈式語法

  下面的代碼是比較經常使用的幾種Masonry的佈局格式,咱們能夠看到都是經過點語法的鏈式調用進行佈局的。以前在學習Java和Android的過程當中接觸過鏈式語法,在Java中要實現這種鏈式語法很簡單,無非就是每一個方法的返回值就是其自己,由於Java的方法調用是經過點語法調用的,因此很容易實現。可是在OC中,方法調用都是經過  [clazz method:parm];  的形式進行調用的,那麼Masonry框架中是怎麼實現的呢?佈局

make.top.equalTo(sv).with.offset(10);

make.left.right.mas_equalTo(sv).mas_offset(0.0f);

make.top.left.bottom.and.right.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));

   一樣的學習方法,咱們來看一下源碼中各個屬性或方法是怎麼實現的,最重要的緣由就是getter方法和Objective-C 裏面,調用方法是可使用點語法的,但這僅限於沒有參數的方法

  • 首先,咱們在用Masonry進行佈局的時候最早用MASConstraintMaker調用一個方位屬性(在MASConstraintMaker中定義了許多方位屬性進行初始化調用,具體有哪些以下MASConstraintMaker.h文件中所示),用點語法調用,例如 make.top ,這時候實際上是調用了其getter方法,而後在getter方法中對該約束的代理進行設置(見下MASConstraintMaker.m文件中標紅註釋處)
    //MASConstraintMaker.h文件
    @interface MASConstraintMaker : NSObject
    
    @property (nonatomic, strong, readonly) MASConstraint *left;
    @property (nonatomic, strong, readonly) MASConstraint *top;
    @property (nonatomic, strong, readonly) MASConstraint *right;
    @property (nonatomic, strong, readonly) MASConstraint *bottom;
    @property (nonatomic, strong, readonly) MASConstraint *leading;
    @property (nonatomic, strong, readonly) MASConstraint *trailing;
    @property (nonatomic, strong, readonly) MASConstraint *width;
    @property (nonatomic, strong, readonly) MASConstraint *height;
    @property (nonatomic, strong, readonly) MASConstraint *centerX;
    @property (nonatomic, strong, readonly) MASConstraint *centerY;
    @property (nonatomic, strong, readonly) MASConstraint *baseline;
    
    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
    
    @property (nonatomic, strong, readonly) MASConstraint *firstBaseline;
    @property (nonatomic, strong, readonly) MASConstraint *lastBaseline;
    
    #endif
    
    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
    
    @property (nonatomic, strong, readonly) MASConstraint *leftMargin;
    @property (nonatomic, strong, readonly) MASConstraint *rightMargin;
    @property (nonatomic, strong, readonly) MASConstraint *topMargin;
    @property (nonatomic, strong, readonly) MASConstraint *bottomMargin;
    @property (nonatomic, strong, readonly) MASConstraint *leadingMargin;
    @property (nonatomic, strong, readonly) MASConstraint *trailingMargin;
    @property (nonatomic, strong, readonly) MASConstraint *centerXWithinMargins;
    @property (nonatomic, strong, readonly) MASConstraint *centerYWithinMargins;
    
    #endif
    
    @property (nonatomic, strong, readonly) MASConstraint *edges;
    @property (nonatomic, strong, readonly) MASConstraint *size;
    @property (nonatomic, strong, readonly) MASConstraint *center;
    ...
    
    @end
    
    
    //MASConstraintMaker.m文件
    @implementation MASConstraintMaker
    
    //每一個方法返回的也是MASConstraint對象,其實是MASViewConstraint、MASCompositeConstraint類型的對象,見最後的函數中標紅的註釋
    - (MASConstraint *)top {
        //將對應的系統自帶的約束佈局的屬性NSLayoutAttributeTop傳入
        return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
    }
    
    //過渡方法
    - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
        return [self constraint:nil addConstraintWithLayoutAttribute:layoutAttribute];
    }
    
    //最終的調用
    - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
        MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute];
        MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute];
        
      ...
    
        //添加約束
        if (!constraint) {
            //設置約束的代理是self
            newConstraint.delegate = self;
            [self.constraints addObject:newConstraint];
        }
        //返回MASViewConstraint類型的對象
        return newConstraint;
    }
    
    ...
    
    @end
  • 而後經過第一步的初始化以後返回的就是一個MASViewConstraint對象了,後面的點語法主要就在於MASViewConstraint中的屬性和方法了,在MASViewConstraint的.h和.m文件中咱們都沒有找到top等方位相關的屬性或方法,可是咱們發現MASViewConstraint是繼承自MASConstraint的,而後咱們發如今MASConstraint中定義了大量的方位相關方法(以下代碼所示),因此相似 make.top.left 前面一個top是調用MASConstraintMaker的方法,後面一個left則是經過點語法調用MASConstraint的方法。可是爲何這些方法能夠進行點語法調用呢?緣由就是在Objective-C 裏面,調用方法是可使用點語法的,但這僅限於沒有參數的方法
    @interface MASViewConstraint : MASConstraint <NSCopying>
    //MASConstraint.h文件
    
    @interface MASConstraint : NSObject
    
    /**
     *    Creates a new MASCompositeConstraint with the called attribute and reciever
     */
    - (MASConstraint *)left;
    - (MASConstraint *)top;
    - (MASConstraint *)right;
    - (MASConstraint *)bottom;
    - (MASConstraint *)leading;
    - (MASConstraint *)trailing;
    - (MASConstraint *)width;
    - (MASConstraint *)height;
    - (MASConstraint *)centerX;
    - (MASConstraint *)centerY;
    - (MASConstraint *)baseline;
    
    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
    
    - (MASConstraint *)firstBaseline;
    - (MASConstraint *)lastBaseline;
    
    #endif
    
    #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)
    
    - (MASConstraint *)leftMargin;
    - (MASConstraint *)rightMargin;
    - (MASConstraint *)topMargin;
    - (MASConstraint *)bottomMargin;
    - (MASConstraint *)leadingMargin;
    - (MASConstraint *)trailingMargin;
    - (MASConstraint *)centerXWithinMargins;
    - (MASConstraint *)centerYWithinMargins;
    
    #endif
    
    ...
    
    @end
    //MASConstraint.m文件
    - (MASConstraint *)top {
        //這裏會調用MASViewConstraint中的addConstraintWithLayoutAttribute:方法
        return [self addConstraintWithLayoutAttribute:NSLayoutAttributeTop];
    }
    
    //MASViewConstraint.m文件
    - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
        NSAssert(!self.hasLayoutRelation, @"Attributes should be chained before defining the constraint relation");
        //調用代理的方法,以前咱們說過設置的代理是MASConstraintMaker對象make,因此調用的其實是MASConstraintMaker添加約束的方法,這就是咱們再上面第一步講到的方法
        return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
    }
    
    //MASConstraintMaker.m文件
    - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
        MASViewAttribute *viewAttribute = [[MASViewAttribute alloc] initWithView:self.view layoutAttribute:layoutAttribute];
        MASViewConstraint *newConstraint = [[MASViewConstraint alloc] initWithFirstViewAttribute:viewAttribute];
        //當傳入的constraint不爲空時,即此調用不是第一個,make.toip.left在left時的調用
        if ([constraint isKindOfClass:MASViewConstraint.class]) {
            //則用MASCompositeConstraint做爲返回值,即組約束
            NSArray *children = @[constraint, newConstraint];
            MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
            //設置代理
            compositeConstraint.delegate = self;
            //從新設置
            [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
           //返回 MASCompositeConstraint對象return compositeConstraint;
        }
    
        if (!constraint) {
            //設置代理
            newConstraint.delegate = self;
            //設置約束
            [self.constraints addObject:newConstraint];
        }
    
        return newConstraint;
    }

2.3 鏈式語法中傳參方法的調用 

  在上一小節咱們提到了鏈式語法的主要緣由在於在Objective-C 裏面,調用方法是可使用點語法的,但這僅限於沒有參數的方法,可是相似mas_equalTo、mas_offset等帶參數傳遞的方法依舊能夠用鏈式語法又是怎麼一回事呢最關鍵的一環就是 blockblock就是一個代碼塊,可是它的神奇之處在於在內聯(inline)執行的時候還能夠傳遞參數。同時block自己也能夠被做爲參數在方法和函數間傳遞。block做爲參數傳遞很常見,就是在咱們的Masonry框架中添加約束的方法 - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block 中就是講一個block做爲參數進行傳遞的。

  一樣在MASConstraint中,咱們能夠看到mas_equalTo、mas_offset等帶參方法的定義以下,咱們能夠看到,方法的定義中並無參數,可是返回值是一個帶參的block,而且該block還返回一個MASConstraint對象(MASViewConstraint或者MASCompositeConstraint對象),因此方法的定義和使用都沒有什麼問題,和上一小節分析的內容差很少。最主要的區別就是這裏返回值爲帶參數的block,而且該block的參數能夠經過咱們的方法進行傳值。關於帶參block做爲返回值得用法能夠參見 此連接的文章

- (MASConstraint * (^)(MASEdgeInsets insets))insets;

- (MASConstraint * (^)(CGFloat inset))inset;

- (MASConstraint * (^)(CGSize offset))sizeOffset;

- (MASConstraint * (^)(CGPoint offset))centerOffset;

- (MASConstraint * (^)(CGFloat offset))offset;

- (MASConstraint * (^)(NSValue *value))valueOffset;

- (MASConstraint * (^)(CGFloat multiplier))multipliedBy;

- (MASConstraint * (^)(CGFloat divider))dividedBy;

- (MASConstraint * (^)(MASLayoutPriority priority))priority;

- (MASConstraint * (^)(void))priorityLow;

- (MASConstraint * (^)(void))priorityMedium;

- (MASConstraint * (^)(void))priorityHigh;

- (MASConstraint * (^)(id attr))equalTo;

- (MASConstraint * (^)(id attr))greaterThanOrEqualTo;
//MASConstraint.m文件
- (MASConstraint * (^)(id))mas_equalTo {
    return ^id(id attribute) {
        //多態調用子類MASViewConstraint或者MASCompositeConstraint的對應方法
        return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}

//MASViewConstraint.m中對應的方法,MASCompositeConstraint其實也相似,只是循環調用每個子約束的該方法
- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation {
    return ^id(id attribute, NSLayoutRelation relation) {
        //若是傳入的參數是一個數組 則逐個約束解析後以組形式添加約束
        if ([attribute isKindOfClass:NSArray.class]) {
            NSAssert(!self.hasLayoutRelation, @"Redefinition of constraint relation");
            NSMutableArray *children = NSMutableArray.new;
            for (id attr in attribute) {
                MASViewConstraint *viewConstraint = [self copy];
                viewConstraint.layoutRelation = relation;
                viewConstraint.secondViewAttribute = attr;
                [children addObject:viewConstraint];
            }
            MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
            compositeConstraint.delegate = self.delegate;
            [self.delegate constraint:self shouldBeReplacedWithConstraint:compositeConstraint];
            return compositeConstraint;
        } else {
            //單一約束 則直接賦值
            NSAssert(!self.hasLayoutRelation || self.layoutRelation == relation && [attribute isKindOfClass:NSValue.class], @"Redefinition of constraint relation");
            self.layoutRelation = relation;
            self.secondViewAttribute = attribute;
            return self;
        }
    };
}

3 Masonry框架的總體運用的理解 

進過上面的原理分析,大致理解了其調用和實現眼裏,接下來,咱們經過下面的這句代碼在容器中的演變過程來進行總體感覺一下,下面的演變過程來自:Masonry源碼學習,原文有幾處有點小問題修改過,你們參考的時候注意甄別和判斷。

make.top.right.bottom.left.equalTo(superview)
  • make.top
    • 生成對象A:MASViewConstraint(view.top)
    • 將A的delegate設爲make
    • 將A放入make的constraints中,此時make.constraints = [A]
    • 返回A
  • make.top.right
    • 生成對象B:MASViewConstraint(view.right)
    • 使用A和B生成MASCompositeConstraint對象C,將C的delegate設爲make
    • 將make.constraints中替換成C,此時make.constraints = [C],C.childConstraints = [A,B]
    • 返回C
  • make.top.right.bottom
    • 生成對象D:MASViewConstraint(view.bottom),將D的delegate爲C
    • 將D放入C.childConstraints中,此時C.childConstraints = [A,B,D]
    • 返回C
  • make.top.right.bottom.left
    • 生成對象E:MASViewConstraint(view.left),E的delegate爲C
    • 將E放入C.childConstraints中,此時C.childConstraints = [A,B,D,E]
    • 返回C
  • make.top.right.bottom.left.equalTo(superview)
    • 會依次調用A,B,D,E的equalTo(superView)

在上面的過程當中能夠看到:

  • 對make.constraints的添加和替換元素的操做
  • 對MASCompositeConstraint對象的添加元素的操做(當.equalTo(@[view1,view2])時就有替換操做了,在裏面沒體現出)。
  • 每一個constraint的delegate爲它的父容器,由於須要父容器來執行添加和替換約束的操做。

4 Masonry框架的總體架構

  盜用iOS開發之Masonry框架源碼解析中的一張圖,這張圖將Masonry框架的架構闡述的很清晰,Masonry框架主要分爲4個部分:

  • View+MASAdditions:最左邊的紅色框的這個類,這是Masonry框架最主要的一個類,主要是最下面的四個添加和修改約束的方法
  • MASConstraintMaker:中間綠色框中的這個類,這是Masonry框架中的過渡類,連接最左邊和最右邊之間的關係,也是鏈式語法的發起點和添加約束的執行點。MASConstraintMaker類就是一個工廠類,負責建立和安裝MASConstraint類型的對象(依賴於MASConstraint接口,而不依賴於具體實現)。
  • 核心類:最右邊的黃色框的這個類羣,這是Masonry框架中的核心基礎類羣,這個類羣又分爲兩個部分:
    • 約束類羣:黃色框上面三個類,其中MASConstraint是一個抽象類,不可被實例化。咱們能夠將MASConstraint是對NSLayoutConstriant的封裝,看作是一個接口或者協議。MASViewConstraint和MASCompositeConstraint都繼承自MASConstraint,其中MASViewConstraint用於定義一個單獨的約束,而MASCompositeConstraint則用於定義一組約束條件,例如定義size、insert等參數時返回的其實都是MASCompositeConstraint。
    • 屬性類羣:主要是指MASViewAttribute,主要是對NSLayoutAttribute的擴展,方便咱們進行約束定義和修改
  • 附屬類羣:還有一些工具類沒有在這張圖中進行展現,例如NSArray+MASAdditions、NSLayoutConstraint+MASDebugAdditions、MASLayoutConstraint等,都定義了一些工具和簡化方法。
相關文章
相關標籤/搜索