你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 手把手教你Masonry的理解

手把手教你Masonry的理解

編輯:IOS開發基礎

我們先來看看是如何開始使用Masonry的,一般我們使用這個布局框架的時候,都會調用以下代碼。。。。。

 [self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(50);
        make.right.mas_equalTo(-50);
        make.top.mas_equalTo(50);
        make.bottom.mas_equalTo(-50);
    }];

我們來分析下這段代碼,UIView類型的使用了mas_makeConstraints這個方法,這個是寫在分類裡面的,有一個block參數,我們看一下裡面的實現代碼:

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

首先設置translatesAutoresizingMaskIntoConstraints屬性為NO

第二行初始化了一個MASConstraintMaker類,那這個類裡面做了什麼操作呢,好吧,本著刨根問底的精神我們繼續往下看

- (id)initWithView:(MAS_VIEW *)view {
    self = [super init];    if (!self) return nil;
    
    self.view = view;
    self.constraints = NSMutableArray.new;    
    return self;
}

將當前的view賦給maker類,然後初始化constraints,這是一個約束數組。

我們仔細看block(constraintMaker);這一行代碼。。。

神馬意思呢?

首先這個block是(void(^)(MASConstraintMaker *))類型的一個參數,我們其實可以更改為其它名稱,感覺用block就有點混淆。。。

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

比如可以更改為上面的形式...

這段代碼的理解就是初始化了一個constraintMaker類,然後設置它的constraint屬性,最後加載安裝(install)

 [self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(50);
        make.right.mas_equalTo(-50);
        make.top.mas_equalTo(50);
        make.bottom.mas_equalTo(-50);
    }];

注意:這種寫法很容易理解為這是一個block,但其實只是在執行一個函數,後面一大塊只不過是函數的一個參數而已,只不過它的參數是一個函數。

它等價與下面的一種寫法:

self.view1.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self.view1];
constraintMaker.left.mas_equalTo(50);
constraintMaker.right.mas_equalTo(-50);
constraintMaker.top.mas_equalTo(50);
constraintMaker.bottom.mas_equalTo(-50);
[constraintMaker install];

那這樣寫的話就不是很方便了,那麼有什麼辦法嗎???

我們把它封裝成一個函數???好的,封裝成一個函數我們要做幾件事情

-(void)addMakeConstraints
{    
   //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];    
    
    //設置它的屬性  
    //  .........    
    
    //加載   
     [constraintMaker install];
}

那麼第二步該怎麼做呢?

傳參數???但是參數有很多呀??怎麼辦??

比如我設置一個字典,裡面用key,value來表示(left:50,right:-50,top:50,bottom:-50)好像也可以,但總覺的不是很方便

-(void)addMakeConstraints:(NSMutableDictionary *)dictionary
{   
    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self]; 
       
    //設置它的屬性 
     //  .........    
    constraintMaker.left.mas_equalTo([dictionary[@"left"] intValue]);
    constraintMaker.right.mas_equalTo([dictionary[@"right"] intValue]);
    constraintMaker.top.mas_equalTo([dictionary[@"top"] intValue]);
    constraintMaker.bottom.mas_equalTo([dictionary[@"bottom"] intValue]);    
    
    //加載    
    [constraintMaker install];
}
NSMutableDictionary *constraint=[[NSMutableDictionary alloc]init];
[constraint setObject:@"50" forKey:@"left"];
[constraint setObject:@"-50" forKey:@"right"];
[constraint setObject:@"50" forKey:@"top"];
[constraint setObject:@"-50" forKey:@"bottom"]; 
[self.view1 addMakeConstraints:constraint];

貌似也可以實現的額,那有沒有什麼更好地辦法呢?我們看下第一種寫法:

-(void)addMakeConstraints
{   
    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];    
    
    //設置它的屬性  
    //  .........    
    
    //加載    
    [constraintMaker install];
}

其實我們中間就是缺了一段代碼:那可以使用delegate嗎

-(void)addMakeConstraints
{    
   //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    
    [self.del addConstraint:constraintMaker];    
    
    //加載    
    [constraintMaker install];
}

-(void)addConstraint:(MASConstraintMaker *)maker
{
    maker.left.mas_equalTo(50);
    maker.right.mas_equalTo(-50);
    maker.top.mas_equalTo(50);
    maker.bottom.mas_equalTo(-50);
}

既然可以用代理實現,那麼block肯定也是可以的

好的,我們改裝成block版本

-(void)addMakeConstraints
{    
    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    
    self.makerBlock(constraintMaker);   
    
    //加載  
   [constraintMaker install];
}
[self.view1 addMakeConstraints];
self.view1.makerBlock=^(MASConstraintMaker *maker){
      
        maker.left.mas_equalTo(50);
        maker.right.mas_equalTo(-50);
        maker.top.mas_equalTo(50);
        maker.bottom.mas_equalTo(-50);
        
};

在這裡,我們是作為一個屬性來使用block的,那麼我們還可以直接用參數作為block來實現的。

也就是說把這段代碼封裝成一個block參數

-(void)addMakeConstraints:(void(^)(MASConstraintMaker *maker))maker
{    //初始化MASConstraintMaker
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    
    maker(constraintMaker);   
    //加載    [constraintMaker install];
}
 [self.view1 addMakeConstraints:^(MASConstraintMaker *make)
    {
        make.left.mas_equalTo(50);
        make.right.mas_equalTo(-50);
        make.top.mas_equalTo(50);
        make.bottom.mas_equalTo(-50);
    }];

至此,這段代碼已經分析完畢,哈哈,總結就一句話:初始化MASConstraintMaker類,然後設置屬性,最後加載,不同的就是將設置屬性作為代碼塊調到實現的類裡面來了而已。

好的 我們看下View+MASAdditions類

/**
 *    following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute */@property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_top;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_right;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_width;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_height;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;
@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000) || (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)@property (nonatomic, strong, readonly) MASViewAttribute *mas_firstBaseline;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_lastBaseline;#endif#if TARGET_OS_IPHONE || TARGET_OS_TV@property (nonatomic, strong, readonly) MASViewAttribute *mas_leftMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_rightMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_topMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottomMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leadingMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailingMargin;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerXWithinMargins;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerYWithinMargins;

這一段是對MASViewAttribute的聲明,看它的名字就知道這一段是對NSLayoutAttribute的封裝,我們知道NSLayoutAttribute只是一些屬性的枚舉,那麼封裝有什麼意義呢?

好吧,我們看下這段代碼:

 [self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.view1.mas_bottom).offset(10);
}];

有個self.view1.mas_bottom,我們知道要設置這個屬性的話,要使用原生的方法:

NSLayoutConstraint *constaint=[NSLayoutConstraint constraintWithItem:self
                                                                       attribute:att
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:attribute.view
                                                                       attribute:attribute.attribute
                                                                      multiplier:1.0
                                                                        constant:space];

在這裡有個toItem,那要設置toItem就必須知道當前是哪個view,如果只有NSLayoutAttribute屬性的話,這段代碼中得toItem是設置不了的。

所以MASViewAttribute便添加了view這個屬性,方便這個地方的設置MAS---View---Attribute,可以這麼理解,哈哈!

/**
 *  Creates a MASConstraintMaker with the callee view.
 *  Any constraints defined are added to the view or the appropriate superview once the block has finished executing
 *
 *  @param block scope within which you can build up the constraints which you wish to apply to the view.
 *
 *  @return Array of created MASConstraints */- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))constraintMakerblock;/**
 *  Creates a MASConstraintMaker with the callee view.
 *  Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
 *  If an existing constraint exists then it will be updated instead.
 *
 *  @param block scope within which you can build up the constraints which you wish to apply to the view.
 *
 *  @return Array of created/updated MASConstraints */- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;/**
 *  Creates a MASConstraintMaker with the callee view.
 *  Any constraints defined are added to the view or the appropriate superview once the block has finished executing.
 *  All constraints previously installed for the view will be removed.
 *
 *  @param block scope within which you can build up the constraints which you wish to apply to the view.
 *
 *  @return Array of created/updated MASConstraints */- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;

這幾個方法分別是添加約束,更新約束以及注銷約束,前面已經將mas_makeConstraints這個方法講的很詳細了,後面兩個方法類似。

只不過多了兩個變量來控制:constraintMaker.updateExisting = YES;constraintMaker.removeExisting = YES;

好的,我們接著向下看:

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

第一步:將maker的view設置為當前view

第二步:設置屬性

第三步:加載

我們看下第二步:

make.left.mas_equalTo(50);
make.right.mas_equalTo(-50);
make.top.mas_equalTo(50);
make.bottom.mas_equalTo(-50);

第二步用的鏈式結構,如果不懂得話可以看看我之前的文章。

make.left返回的MASConstraint類型

- (MASConstraint * (^)(id attr))mas_equalTo;
- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo;
- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo;
- (MASConstraint * (^)(id))mas_equalTo {   
           return ^id(id attribute) {       
                 return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}

然後執行mas_equalTo的方法:

它的返回值是:MASConstraint * (^)(id) 一個block。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved