美文网首页牛叉的demo学无止境ios11适配
简单好用的iOS自动布局框架

简单好用的iOS自动布局框架

作者: fruitymoon | 来源:发表于2017-02-06 17:13 被阅读3381次

    有感于iOS自动布局代码的冗长和繁琐,闲来无事,便自己封装了一下。
    写的过程中我借鉴了NSLayoutAnchor和masonry的一些思路,写了充分的单元测试用例,并对框架的性能(耗时和内存占用)做了一个简单评估。

    优点

    • 简单,17KB大小。易用,对于许多布局,用起来跟frame差不多
    • 支持iOS8和swift
    • 速度是masonry的1.7倍,接近系统方法速度,占用内存小
    • 跟踪所有约束,不需要额外写成员属性引用约束
    • 充分的单元测试
    • 支持iOS11,相对safeAreaLayoutGuide的布局约束书写非常简便!
    和系统方法、Masonry在性能上的比较

    设置约束

    所有约束设置都遵循系统的公式:

    firstItem.firstAttribute {=,<=,>=} secondItem.secondAttribute * multiplier + constant
    

    简便写法(适用于NSLayoutRelationEqual、multiplier = 1 且除了宽、高以外的约束的constant = 0的情况)

    [self.redView activateConstraints:^{
        self.redView.height_attr.constant = 100; // redView的高度 = 100
        self.redView.width_attr = self.blueView.width_attr; // redView的宽度 = blueView的宽度
        self.redView.top_attr = self.blueView.top_attr; // redView的顶部 = blueView的顶部
        self.redView.left_attr = self.blueView.right_attr; // redView的左边 = blueView的右边
    }];
    

    常规写法

    [self.redView activateConstraints:^{
        self.redView.height_attr.constant = 150; // redView的高度 = 150
        [self.redView.width_attr equalTo:self.blueView.width_attr constant:50]; // redView的宽度 = blueView的宽度 + 50
        [self.redView.top_attr equalTo:self.blueView.top_attr constant:-10]; // redView的顶部 = blueView的顶部 - 10
        [self.redView.left_attr greaterThan:self.blueView.right_attr constant:20]; // redView的左边 >= blueView的右边 + 20
    }];
    

    activateConstraints方法会将block里所有约束都绑定给调用者,这里就是self.redView,这么做是为了方便以后获取约束。
    也可以用更接近系统的风格设置约束,但这样以后想获取特定的某个约束就比较麻烦,需要创建一个成员变量引用以后想改变的约束。

    NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:4];
    [arrayM addObject:[self.redView.height_attr equalTo:nil constant:100]];
    [arrayM addObject:[self.redView.width_attr equalTo:self.blueView.width_attr]];
    [arrayM addObject:[self.redView.top_attr equalTo:self.blueView.top_attr]];
    [arrayM addObject:[self.redView.left_attr equalTo:self.blueView.right_attr]];
    [NSLayoutConstraint activateConstraints:arrayM];
    

    更新safeAreaLayoutGuide布局写法,不需要写版本判断

    [self.redView activateConstraints:^{
        self.redView.height_attr.constant = 100; // redView的高度 = 100
        self.redView.width_attr = self.blueView.width_attr; // redView的宽度 = blueView的宽度
        self.redView.top_attr = self.view.top_attr_safe; // redView的顶部 = view的safeAreaLayoutGuide的顶部,非iOS11则是view的顶部
        self.redView.left_attr = self.view.right_attr_safe; // redView的左边 = view的safeAreaLayoutGuide的右边,非iOS11则是view的右边
    }];
    

    改变约束值

    self.blueView.width_attr.constant = 100;
    

    或者

    [self.redView constraintAccordingToAttribute:self.redView.height_attr].constant = 100;
    

    获取约束

    获取非常方便,当初创建约束是怎样的相对关系,通过相同的关系就可以获取约束。

    NSLayoutConstraint *cons = [self.titleLabel constraintAccordingToAttribute:self.titleLabel.bottom_attr andAttribute:self.subtitleLabel.top_attr];
    

    激活和关闭约束

    [self.redView activateConstraintAccordingToAttribute:self.redView.height_attr];
    [self.redView deactivateConstraintAccordingToAttribute:self.redView.height_attr];
    

    注意:调用deactivateConstraintAccordingToAttribute会将该约束对象销毁,这里保持跟系统的deactivateConstraint方法一致。如果只是想暂时关闭约束,以后想再activate,则应该获取约束后,设置.active = NO

    解释一下核心方法 -(void)activateConstraints:(void (^)())constraints;
    这是UIView的一个对象方法,一般来说每个UIView的布局代码写在自己的block里, 只有调一次该方法,才会给这个方法的调用者创建一个用来引用布局对象的可变数组,以后才可以通过这个调用者拿到里面的布局对象。
    并且只要调用了一次该方法,以后即使不在该方法的block里写的约束,约束的firstItem如果和该方法的调用者是一个对象,也会把这个约束添加到firstItem(调用者)的数组里
    如果调用了activateConstraints后,又希望移除对应view的数组,可以调用
    - (void)deactivateAllConstraintsAndAssociatedObjects

    具体使用请移步github下载示例代码。


    添加到项目

    使用CocoaPods
    在podfile中加入 'NSLayoutConstraint-SSLayout'
    直接使用源代码
    将Source文件夹下的文件copy到项目

    传送门:https://github.com/suruihai/NSLayoutConstraint-SSLayout

    相关文章

      网友评论

      • 舒马赫:推荐使用xml的布局库FlexLib,采用前端布局标准flexbox(不使用autolayout),支持热刷新,国际化等。可以到这里了解详细信息:

        https://github.com/zhenglibao/FlexLib
      • f44df7bd76c4:大神 有个问题 在进行iPhone X适配时 如tableview这种会占满屏的控件 经常需要上下各让出安全距离 我尝试过同时设置top_attr bottom_attr这两个属性 但是只有一个会生效 这样的画只能判断机型去约束tableview的宽度么?
        f44df7bd76c4:@fruitymoon tableView在vc上 直接使用vc.view的top_attr_safe和bottom_attr_safe布局 结果只有top_attr_safe生效了 单一使用top_attr_safe或bottom_attr_safe倒是都可以生效
        fruitymoon:@胸前挂俩旺仔小馒头 tableView直接相对他父view的top_attr_safe 和 bottom_attr_safe 布局就可以了,应该都可以生效的
      • 脑袋好重:看起来不错
      • GodSunsh:觉得很有用,我们就是写死的我很不喜欢
      • 爱丶不失手:mark一波 :yum:
      • 简书lu:看了你的简书,可以麻烦大神写篇文章介绍一下单元测试和UITest吗?看你的文章简短易懂~求指导
        fruitymoon:谢谢,我不是大神哈,相互交流。测试这块水很深,有时间的话我会写一些测试相关的东西:grin:
      • 雨天多久就:mark!回来试试

      本文标题:简单好用的iOS自动布局框架

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