iOS 开发中的得力鲁班尺 - SnapKit | 掘金技术征文

4,177 阅读4分钟

SnapKit

先来谈谈何为 DSL

DSL(Domain Specific Language),即领域特定语言,指的是一种针对特定问题的编程语言,与此相对便是 GPL(General Purpose Language),也就是我们平常所用的编程语言,用途更为宽泛。DSL含有建模所需的特定语法和语义,因此可在与问题域相同的抽象层次高效对概念建模。

A specialized computer language designed for a specific task.

—— Wikipedia

软件开发大师 Martin Fowler 的解读则更加明晰

DSL 通过在表达能力上做的妥协换取在某一领域内的高效。

举个栗子,正则表达式(Regex)SQLHTML & CSS,便是 DSL。

那么,为什么要先讲 DSL,因为 SnapKit 就是针对高效使用 AutoLayout 的 DSL。是的,所以 SnapKit 不仅仅是一个个框架,它是一门编程语言。

安装 SnapKit

使用 CocoapodsCarthage 可以非常方便地进行安装,就不多费篇幅了

  • Cocoapods

    pod 'SnapKit'

  • Carthage

    github "SnapKit/SnapKit"

基本使用

在开篇我们知道了 SnapKit 是一门编程语言,并且是一门专门针对高效使用 AutoLayout 的特定语言,因此它被设计得十分简便易用。

SnapKit-Sample

let containerView = UIView()
superview.addSubview(containerView)

containerView.snp.makeConstraints { (make) -> Void in
    make.top.equalTo(superview).offset(5)
    make.left.equalTo(superview).offset(5)
    make.bottom.equalTo(superview).offset(-5)
    make.right.equalTo(superview).offset(-5)

    // 或者可以更简洁
    // make.edges.equalTo(superview).inset(UIEdgeInsetsMake(5, 5, 5, 5))
}

let avatarView = UIView()
containerView.addSubview(avatarView)

avatarView.snp.makeConstraints { (make) -> Void in
    make.size.equalTo(35)
    make.left.equalTo(superview).offset(5)
    make.centerY.equalTo(container)
}

于是,SnapKit 便能够将所有约束添加妥当。可以看到,这样的写法非常简洁明了,并且可读性高。

几个至关重要的 Tips :

  • 确定最佳父视图布置约束
  • 记住安装的约束以便在之后可以快速移除
  • 确保相关视图 setTranslatesAutoresizingMaskIntoConstraints(false)

相等(equalTo)之外

.equalTo 相当于 NSLayoutRelation.Equal

.lessThanOrEqualTo 相当于 NSLayoutRelation.LessThanOrEqual

.greaterThanOrEqualTo 相当于 NSLayoutRelation. GreaterThanOrEqual

这三个约束关系可接受以下某个参数:

1.视图属性
make.centerX.lessThanOrEqualTo(view2.snp.left)

2.某个视图 UIView/NSView

用于描述与其他视图之间的布局关系

// 这两行语句是等效的
make.left.greaterThanOrEqualTo(label)
make.left.greaterThanOrEqualTo(label.snp.left)
3.固定常量

用于描述本身的宽高约束

//  200 <= 宽度 <= 400
make.width.greaterThanOrEqualTo(200)
make.width.lessThanOrEqualTo(400)

用于描述与父视图的布局关系

// 创建约束使得 view.left <= view.superview.left + 10
make.left.lessThanOrEqualTo(10)

更多固定常量的示例

make.top.equalTo(42)
make.height.equalTo(20)
make.size.equalTo(CGSizeMake(50, 100))
make.edges.equalTo(UIEdgeInsetsMake(10, 0, 10, 0))
make.left.equalTo(view).offset(UIEdgeInsetsMake(10, 0, 10, 0))

学会应用约束的优先级

.priority 允许你指定某个约束的优先级

优先级一般跟在约束链的末尾:

make.top.equalTo(label.snp.top).priority(600)

组合多种约束

SnapKit 支持同时组合不同的约束条件,方便高效

边缘(edges)

make.edges.equalTo(view2);
make.edges.equalTo(superview).inset(UIEdgeInsetsMake(5, 10, 15, 20))
尺寸(size)
make.size.greaterThanOrEqualTo(titleLabel)
make.size.equalTo(superview).offset(CGSizeMake(100, -50))
居中(center)
make.center.equalTo(button1)
make.center.equalTo(superview).offset(CGPointMake(-5, 10))

懂得改变

有时我们需要通过改变一些现有的布局约束来实现动画,又或者是根据不同情况来调整布局,因此,SnapKit 也提供了不同的方式来实现。

1. 约束引用

即通过添加对应约束的全局引用变量,来实现对约束的控制

var topConstraint: Constraint? = nil

...

// 创建布局约束
view1.snp.makeConstraints { (make) -> Void in
  self.topConstraint = make.top.equalTo(superview).offset(padding.top).constraint //添加全局引用
  make.left.equalTo(superview).offset(padding.left)
}
...
// 之后若是要移除该约束
self.topConstraint.uninstall()

// 或者更改该约束
self.topConstraint.updateOffset(5)

这个方式在大多数情况下有些繁琐,因此在开发工程中并不常用。

2. snp.updateConstraints
// 官方推荐在这个方法中来添加或更改布局
override func updateConstraints() {
    self.growingButton.snp.updateConstraints { (make) -> Void in
        make.center.equalTo(self);
        make.width.equalTo(self.buttonSize.width).priority(250)
        make.height.equalTo(self.buttonSize.height).priority(250)
        make.width.lessThanOrEqualTo(self)
        make.height.lessThanOrEqualTo(self)
    }

   // 别忘记在最后调用父类的该方法
     super.updateConstraints()
}

这是在开发中最为常用的修改布局的方式

3. snp.remakeConstraints

这个方法与 snp.updateConstraints 十分相似,不同的是,这个方法会先将已存在的SnapKit布局约束全部移除。

func changeButtonPosition() {
  self.button.snp.remakeConstraints { (make) -> Void in 
    make.size.equalTo(self.buttonSize)

    if topLeft {
      make.top.left.equalTo(10)
    } else {
      make.bottom.equalTo(self.view).offset(-10)
      make.right.equalTo(self.view).offset(-10)
    }
  }
}

总结

说白了,SnapKit 真的是手动 AutoLayout 的超级利器。
另外,它也有 Objective-C 版本,Masonry,设计理念与使用方法一致。

更多参考


掘金技术征文活动链接:

juejin.cn/post/684490…