美文网首页 iOS进阶之Masonry
iOS进阶之masonry细致入微(二)

iOS进阶之masonry细致入微(二)

作者: 天蓬大元 | 来源:发表于2019-01-08 09:41 被阅读0次
    在上篇文章中,我们了解到,当为某一个view添加约束时,masonry的代码执行顺序是下面这样的。我们通过细致的分析了解到一条约束在被装载到view之前,masonry都做了什么。其他三个约束的处理亦然。
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    
    ^(MASConstraintMaker *make) {
        make.left.mas_equalTo(lable.superview.mas_left).offset(10);
        make.right.mas_equalTo(-10);
        make.top.mas_equalTo(0);
        make.bottom.mas_equalTo(0);
    }
    
    return [constraintMaker install];
    
    我们这篇文章主要讲述,如何将存储在MASConstraintMaker对象中的约束装载到view上。在开始之前,我们简短的回顾一个约束的收集过程。
    1,创建一个MASConstraintMaker类对象爱丽丝,她持有要添加约束view乔治,并且持有一个数组,用来收集约束。
    2,爱丽丝通过.left创建一个MASViewConstraint类对象葛二蛋,葛二蛋持有了left约束条件,并被保存在爱丽丝的数组中。
    3,葛二蛋通过mas_equalTo获取到相对于父类的约束并存储
    4,葛二蛋通过offset获取到子类与父类约束之间的改变值。
    .right和.top和.bottom的处理情况与.left类似。
    至此,葛二蛋兄弟4个持有了乔治所有的约束条件,而爱丽丝持有了乔治和葛二蛋兄弟4个。那接下来就是爱丽丝如何将二蛋四兄弟装载到乔治身上,完成约束的添加任务。
    好,我们开始进入正题:[constraintMaker install]。
     - (NSArray *)install {
        ///注意这里的self指代的是谁。
        ///这个是干什么的,我们先不管,你只要知道这里if的代码不会被执行
        if (self.removeExisting) {
            NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
            for (MASConstraint *constraint in installedConstraints) {
                [constraint uninstall];
            }
        }
        ///你不应该还不知道这里的self是谁。
        NSArray *constraints = self.constraints.copy;
        for (MASConstraint *constraint in constraints) {
            ///取出来的就是二蛋4兄弟之一
            constraint.updateExisting = self.updateExisting;
            ///调用了葛二蛋的装载方法。
            [constraint install];
        }
        ///爱丽丝的数组被清空,但constraints仍然保存了一份二蛋4兄弟。这里你应该知道copy的用法。体会这里作者为什么用copy处理一下数组。
        [self.constraints removeAllObjects];
        ///返回了二蛋4兄弟,注意,此时爱丽丝没有再持有这四兄弟。
        return constraints;
    }
    
    不要着急,我们掰开了一个一个看。
    二蛋的装载 [constraint install];
    - (void)install {
        ///如果已经被装载,则不需要重复装载
        if (self.hasBeenInstalled) {
            return;
        }
        这个我们先不管
        if ([self supportsActiveProperty] && self.layoutConstraint) {
            self.layoutConstraint.active = YES;
            [self.firstViewAttribute.view.mas_installedConstraints addObject:self];
            return;
        }
    
        MAS_VIEW *firstLayoutItem = self.firstViewAttribute.item;
        ///这个是要添加约束的view的自己的约束项
        NSLayoutAttribute firstLayoutAttribute = self.firstViewAttribute.layoutAttribute;
        MAS_VIEW *secondLayoutItem = self.secondViewAttribute.item;
        ///这个是相对于父视图的约束项
        NSLayoutAttribute secondLayoutAttribute = self.secondViewAttribute.layoutAttribute;
    
        // alignment attributes must have a secondViewAttribute
        // therefore we assume that is refering to superview
        // eg make.left.equalTo(@10)
        ///这里作者的注释已经写的很清楚了,如果你写出了make.left.equalTo(@10)这样的约束,就会用到这个处理,自动获取父类,并让父类的对比约束和子类一样。
        if (!self.firstViewAttribute.isSizeAttribute && !self.secondViewAttribute) {
            ///父类
            secondLayoutItem = self.firstViewAttribute.view.superview;
            ///父类的约束条件取子类的约束条件
            secondLayoutAttribute = firstLayoutAttribute;
        }
        ///好,接下来的代码就是核心中的核心了。调用系统的autolayout进行约束处理。MASLayoutConstraint继承自NSLayoutConstraint。扩展了一个有意思的key,你能体会到这个key的用处吗?如果你不数熟悉autolayout的API,记得了解一下,这里不做过多解释。你可以不用,但你最好知道。
        MASLayoutConstraint *layoutConstraint
        = [MASLayoutConstraint constraintWithItem:firstLayoutItem
                                        attribute:firstLayoutAttribute
                                        relatedBy:self.layoutRelation
                                           toItem:secondLayoutItem
                                        attribute:secondLayoutAttribute
                                       multiplier:self.layoutMultiplier
                                         constant:self.layoutConstant];
        ///其实看到这里,你就应该思索,masonry的功能,不仅仅是添加普通约束。
        layoutConstraint.priority = self.layoutPriority;
        layoutConstraint.mas_key = self.mas_key;
        ///这个是干什么的?
        if (self.secondViewAttribute.view) {
            MAS_VIEW *closestCommonSuperview =       [self.firstViewAttribute.view mas_closestCommonSuperview:self.secondViewAttribute.view];
        NSAssert(closestCommonSuperview,
                 @"couldn't find a common superview for %@ and %@",
                 self.firstViewAttribute.view, self.secondViewAttribute.view);
            ///关键理解这个。这里还是要说,你真的需要理解一下autolayout是如何进行布局的。公共父类进行布局约束。
            self.installedView = closestCommonSuperview;
        } else if (self.firstViewAttribute.isSizeAttribute) {
            /**///了解了这个,就好理解这里的判断了。
                - (BOOL)isSizeAttribute {
                        return self.layoutAttribute == NSLayoutAttributeWidth
        || self.layoutAttribute == NSLayoutAttributeHeight;
                }
            */
            self.installedView = self.firstViewAttribute.view;
        } else {
            ///view相对于view.superView进行布局
            self.installedView = self.firstViewAttribute.view.superview;
        }
    
    
        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];
        }
    }
    
    到这里,整个装载过程就完成了。但我相信,你还没有很好的理解整个装载过程。不要心急。这个过程只是引导大家对masonry做常用最简单的一个约束过程有一个大致的了解。接下来,我将以这次装载过程为线索,详细的去理一理这个框架的脉络和文件,对源码进行逐行的分析。我相信,有了前面这个简单的了解,我们对于后面的理解会容易得多。

    相关文章

      网友评论

        本文标题:iOS进阶之masonry细致入微(二)

        本文链接:https://www.haomeiwen.com/subject/pcxvrqtx.html