Masonry源码分析(上)

作者: YYYYYY25 | 来源:发表于2018-05-15 17:24 被阅读83次

    重点及目标

    1 熟悉Masonry基本执行步骤和封装原理
    2 理解链式编程和面向对象原理
    3 设计模式:策略模式?抽象工厂模式?


    前言:

    由于前段时间一个偶然的机会在腾讯课堂听了一节关于编程原理的课程,课程中对于链式编程和Masonry做了基本的介绍,也给我留下了一些疑问,所以决定工作之余再花点时间整理一下。

    网络上对于Masonry源码分析的文章也很多,每篇文章的切入点和分析思路也各有不同,我的思路很简单,相信大家刚接触Masonry的时候都见过下面这段代码,这篇文章的目的就是搞清楚这段代码的背后是怎么执行的,有什么值得学习的地方。

    【更新5.18】一个优秀的第三方库会有很多巧妙的设计思路,Masonry的文件结构中有一个MASConstraint抽象类,我之前理解为工厂模式,但是它又更偏向方法的封装,所以最后我觉得它是策略模式,这里给大家留下一个问题吧,你们怎么看?

    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        // 这里例句了几个比较有代表性的方法(写法有很多)
        make.top.mas_equalTo(100);
        make.centerX.equalTo(self.mas_centerX);
        make.width.and.height.mas_equalTo(100);
    }];
    

    开始之前,先讲点关于UI搭建的废话:

    1 纯代码布局:优点是开发时你可以更注重编码的环节,也方便他人对项目的维护和代码的重用;缺点也显而易见,就是慢!而且如果你不理解苹果对界面布局的规则和理想的话,遇到问题难以解决。
    2 xib、StoryBoard:这套工具其实远比你想象的强大和易用,你可以在运行之前更直观的看到界面的构成,使用起来也更容易上手。当然他也有明显的缺点,就是对于页面的属性可以多方位的管理,在不同地方修改同一属性是很难debug的,并且即便你使用xib布局,也很难摆脱代码的辅助。

    这两种方式我先后都使用过,个人的建议是先从Interface Build上手,理解约束的概念和布局的原理,然后再过度到纯代码的编写,思想的嵌套不影响工具的转换。记住一句话:约束的搭建是由内向外的,想清楚界面的层次,把每层的约束设全面,一般都不会出错。

    正文

    直接从源码分析开始,如果想了解Masonry基本用法,请参考:Masonry详解
    当然更推荐的方式是GitHub:SnapKit/Masonry

    一、Masonry文件结构
    Masonry目录

    图中标出了比较重要的类,下面按顺序简单解释一下:

    1.1 View-MASAdditions

    这是一个UIView的分类,你肯定非常熟悉,看一下代码就懂了

    - (instancetype)mas_closestCommonSuperview:(MAS_VIEW *)view;
    - (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
    - (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
    - (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;
    @property (nonatomic, strong, readonly) MASViewAttribute *mas_left;
    @property (nonatomic, strong, readonly) MASViewAttribute *mas_top;
    ....
    

    这些方法都是这个分类中的,如果你还是很陌生,那继续看:

    // 设置约束一定会调用的方法 mas_makeConstraints:
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
    }];
    // view.mas_leading 就是在view的分类中添加了mas_leading属性
    make.leading.equalTo(view.mas_leading).with.offset(10);
    

    ps:一般情况下在分类中添加属性需要使用runtime进行动态绑定,但是这里的属性添加使用了 面向对象 的思想,返回一个约束属性的对象

    - (MASViewAttribute *)mas_leading {
        return [[MASViewAttribute alloc] initWithView:self layoutAttribute:NSLayoutAttributeLeading];
    }
    
    1.2 MASConstraintMaker

    这是创建约束的工厂方法类,创建的时候会初始化一个约束数组,在mas_makeConstraints:方法最后会把约束数组中的元素进行组装,达到设置约束的目的。

    1.3 MASConstraint相关

    这是一个约束抽象类,实际的工作都安排给他的两个子类去做:MASViewConstraint和MASCompositeConstraint。

    /**
     *  Enables Constraints to be created with chainable syntax
     *  Constraint can represent single NSLayoutConstraint (MASViewConstraint) 
     *  or a group of NSLayoutConstraints (MASComposisteConstraint)
     */ 
    @interface MASConstraint : NSObject
    

    MASViewConstraint:代表单个约束
    MASComposisteConstraint:代表组合约束
    MASViewAttribute:视图属性


    他们的关系
    1.4 MASLayoutConstraint

    这个类只是对NSLayoutConstraint的封装,在.m文件中没有做任何实现


    小结:

    本篇文章简单介绍了Masonry的文件结构,在理解下面这段代码之前,我特意做了一个图,希望能让大家把刚刚介绍的文件对应在代码中:

    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(100);
        make.centerX.equalTo(self.mas_centerX);
        make.width.and.height.mas_equalTo(100);
    }];
    
    Masonry文件在代码中体现

    接下去会按步骤介绍mas_makeConstraints:方法调用中具体的实现步骤,请看:Masonry源码分析(下)

    相关文章

      网友评论

        本文标题:Masonry源码分析(上)

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