三方库iOS Developer

Masonry框架学习

2016-07-03  本文已影响370人  肥猫记

Masonry

使用

  • 关键方法:- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
  • 约束方法除了equalTo,还有lessThanOrEqualTo和greaterThanOrEqualTo
  • 当已有约束需要更新时调用mas_updateConstraints方法
  • mas_remakeConstraints方法会先清除当前所有约束再布置
  • Masonry的五大参数:Attribute(属性) ,Relation(关系),Multiplier(乘),Constant(大小),Priority(优先级)
    //一个系统的约束创建方法
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top]
                                  
    //mas_makeConstraints
    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(superView).with.offset(10);
        make.left.equalTo(superView).with.offset(10);
        make.bottom.equalTo(superView.mas_bottom).with.offset(-10);
        make.right.equalTo(superView.mas_right).with.offset(-10);
//        等价于
//        make.edges.equalTo(superView).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
//        会自动调用view1.translatesAutoresizingMaskIntoConstraints = NO;
    }];
    //mas_remakeConstrains
    [self.button mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(self.buttonSize);

        if (topLeft) {
            make.top.and.left.offset(10);
        } else {
            make.bottom.and.right.offset(-10);
        }
    }];
    //mas_updateConstraints
        [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];

    //according to apple super should be called at end of method
    [super updateConstraints];
}

原理

//设置约束方法
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    constraintMaker.updateExisting = YES;
    block(constraintMaker);
    return [constraintMaker install];
}
//MASConstraintMaker的install方法
- (NSArray *)install {
    //判断是否有移除所有已存在的约束标志
    if (self.removeExisting) {
        NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
        for (MASConstraint *constraint in installedConstraints) {
            [constraint uninstall];
        }
    }
    //取出maker对象中的所有约束
    NSArray *constraints = self.constraints.copy;
    for (MASConstraint *constraint in constraints) {
    //设置已经设置了约束的标志
        constraint.updateExisting = self.updateExisting;
        //调用MASConstraint的install方法
        [constraint install];
    }
    [self.constraints removeAllObjects];
    return constraints;
}
//MASViewConstraint(MASConstraint子类)的install方法
- (void)install {
    ...
    ...
    MASLayoutConstraint *layoutConstraint
        = [MASLayoutConstraint constraintWithItem:firstLayoutItem
                                        attribute:firstLayoutAttribute
                                        relatedBy:self.layoutRelation
                                           toItem:secondLayoutItem
                                        attribute:secondLayoutAttribute
                                       multiplier:self.layoutMultiplier
                                         constant:self.layoutConstant];
    
    ...
    ...
    MASLayoutConstraint *existingConstraint = nil;
    if (self.updateExisting) {
        existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint];
    }
    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];
    }
}

MASConstraint和其子类

Masonry链式语法实现原理

进入文件中可发现left,top..等maker属性方法返回都是MASConstraint类型,而MASConstraint中也有这些相同的属性方法,返回值依是MASCompositeConstraint对象,所有才能像make.top.left.right...这样使用Masonry,具体实现原理如下

 1、MASConstraint的left方法:

    - (MASConstraint *)left {
        return [self addConstraintWithLayoutAttribute:NSLayoutAttributeLeft];
    }
    它会跳转到MASViewConstraint的addConstraintWithLayout...方法
--------------------------------------------    
    2、MASViewConstraint的addConstraintWithLayout...方法

    - (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
        return [self.delegate constraint:self addConstraintWithLayoutAttribute:layoutAttribute];
    }
    它会调用delegate的constraint...delegate就是MASConstraintMaker,来看看吧
--------------------------------------------
    3、MASConstraintMaker的代理方法

    - (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute {
            MASCompositeConstraint *compositeConstraint = [[MASCompositeConstraint alloc] initWithChildren:children];
            [self constraint:constraint shouldBeReplacedWithConstraint:compositeConstraint];
            return compositeConstraint;
    }
    创建的compositeConstraint布局时,就会调用children的install方法设置约束,从而达到通过点语法

上一篇下一篇

猜你喜欢

热点阅读