语言: swift, 版本:swift5,XCode:10.2
写作时间:2019-06-19

Introduction to SnapKit: Make Auto Layout Easy for iOS App Development

SnapKit简介

相对布局,Swift用SnapKit,跟Objc用Masonry是一个团队维护的,所以语法糖都一毛一样。github Star > 1.5w, 信得过!

Demo gif:

1. 相对于父容器的布局,80%场景都可解决

注意:设置相对布局之前,前置条件为把addSubview加入父视图

跟父界面的布局一毛一样,也就是逆时针方向上左下右,可以设置距离边界偏移量offset(上和左是用正数,下和右是用负数表示缩进), 设置优先级priority,默认是1000; 常用情况的subview的是3个方向跟父界面相对,缺少一个方向,用高度或者宽度定位:

viewTop = UIView() viewContainer.addSubview(viewTop) viewTop.backgroundColor = innerViewBGColor viewTop.snp.makeConstraints { (make) in make.top.equalTo(viewContainer).offset(40).priority(750) make.left.equalTo(viewContainer) make.bottom.equalTo(viewContainer) make.right.equalTo(viewContainer) //make.height.equalTo(100) }

如果跟父视图都一致,有内边距可以用UIEdgeInsets:

lblTitle.snp.makeConstraints { (make) in make.edges.equalTo(viewTop).inset(UIEdgeInsets(top: 0.0, left: 16.0, bottom: 0.0, right: 0.0)) } 2. 保存约束条件Constraint,做动画的时候可以直接修改约束

保存约束self.centerYConstraint,实际上上面Y方向已经居中

func setupContainerView() { viewContainer = UIView() self.addSubview(viewContainer) viewContainer.snp.makeConstraints { (make) in self.centerYConstraint = make.centerY.equalTo(self).constraint } }

更新Y方向向下偏移10px:

centerYConstraint.update(offset: 10)self.setNeedsLayout()UIView.animate(withDuration: 0.4) { self.layoutIfNeeded()} 3. 链式设计模式

上面为啥centerYConstraint跟make的用法一样? 这是链式设计模式,也就是left, top, centerY, 等方法返回都是self自己。比如left, top都是跟父视图一样,也可以这么写:

viewTop.snp.makeConstraints { (make) in make.left.top.equalTo(viewContainer) // the same as below // make.left.equalTo(viewContainer) // make.top.equalTo(viewContainer) }

看源码是如何使用链式设计模式的:

public var left: ConstraintMakerExtendable { self.description.attributes += .left return self}public var top: ConstraintMakerExtendable { self.description.attributes += .top return self}public var bottom: ConstraintMakerExtendable { self.description.attributes += .bottom return self}public var right: ConstraintMakerExtendable { self.description.attributes += .right return self} 4. 4. 重新设置约束remakeConstraints

清空原有约束,重新定义约束用remakeConstraints:

txtEmail.snp.remakeConstraints { (make) in make.top.equalTo(viewTop.snp.bottom).offset(16) make.left.equalTo(viewContainer).offset(8) make.right.equalTo(viewContainer).offset(-8) make.height.equalTo(textfieldHeight) } 5. 5. 更新已经存在的约束

如果原有约束存在,需要更新约束 updateConstraints:

activityIndicator.snp.updateConstraints { (make) in make.centerY.equalTo(viewContainer).offset(-containerViewHeight/2 – 20)} 6. 为啥不会循环引用

view自己调用的方法,方法中的参数make又是自己,为啥不会循环引用

btnConnect.snp.makeConstraints { (make) in make.top.equalTo(viewBottom) make.right.equalTo(viewBottom) make.bottom.equalTo(viewBottom) make.width.equalTo(connectButtonWidth)}

看源码可以知道端倪,方法中的block没有被self引用,也就不会存在循环引用。

public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) { ConstraintMaker.makeConstraints(item: self.view, closure: closure) } 7. 总结

SnapKit 用第一节的方法可以解决80%的常见布局功能,有动画需求参照下面的3个小节也可以解决。完整教程请参照:Introduction to SnapKit: Make Auto Layout Easy for iOS App Development

代码下载

https://github.com/zgpeace/SnapkitDemo

参考

https://www.appcoda.com/snapkit/
https://github.com/SnapKit/SnapKit
https://github.com/SnapKit/Masonry