当前位置: 首页 > news >正文

SnapKit 最佳实践

用了 SnapKit 很久,一开始觉得这就是个很简单的语法糖,后面用着用着还是觉得有点磕磕绊绊,所以又回去看过了一遍官方文档,发现了几个 best practice 是我之前一直没留意到的,就写出来分享一下。

inset 是个高级抽象

刚开始使用 SnapKit 时,我都是直接使用 offset 来控制边距的:

view.snp.makeConstraints {
    $0.top.left.equalToSuperview().offset(10)
    $0.right.bottom.equalToSuperview().offset(-10)
}
复制代码

offset 使用的是绝对值,例如说 superviewbottom 是 300 时,那 viewbottom 就会是 300 + (-10)

为了简化在这种情况下的语法,SnapKit 封装了一个高级抽象 inset,帮我们自动转换:

switch layoutAttribute {
case .left   : return value.left
case .top    : return value.top
case .right  : return -value.right
case .bottom : return -value.bottom
...
}
复制代码

使用 inset,之前的代码就可以简化成这样:

view.snp.makeConstraints {
    $0.top.left.bottom.right.equalToSuperview().inset(10)
    // 或者直接使用 edges
    $0.edges.equalToSuperview().inset(10)
}
复制代码

总结一句就是,在描述 view 与 superview 关系时,应该使用 inset,而描述 view 与同一层级的其它 view 时,应该使用 offset

不可忽视的 ConstraintConstantTarget

在一个 view 里,一般来说设计师都会给 content 一个统一的边距,类似于 h5 里 padding 的概念,在构建约束时我们经常会把这个 padding 分散到各处:

container.addSubview(a)
container.addSubview(b)

a.snp.makeConstraints {
    $0.top.equalToSuperview().inset(5)
    $0.left.right.equalToSuperview().inset(15)
}

b.snp.makeConstraints {
    $0.top.equalTo(a.snp.bottom).offset(5)
    $0.left.right.equalToSuperview().inset(15)
    $0.bottom.equalToSuperview().inset(5)
}
复制代码

同是 padding 但却分散去处理是一件很糟糕的事情,更好的方式是使用已有的抽象 UIEdgeInsets

在调用 equalTo, offset 或者 inset 传入数值时,我们会发现传入的参数类型实际上只有 ConstraintConstantTarget,这是一个协议,SnapKit 把它作为一个类簇在使用,通过一个方法将它转化为 CGFloat 来作为 constraint 的 constant

UIEdgeInsets 也遵循了这个协议,所以我们可以更加优雅地去处理边距:

let containerInsets = UIEdgeInsets(top: 5, left: 15, bottom: 5, right:15)

container.addSubview(a)
container.addSubview(b)

a.snp.makeConstraints {
    $0.top.left.right.equalToSuperview().inset(containerInsets)
}

b.snp.makeConstraints {
    $0.top.equalTo(a.snp.bottom).offset(5)
    $0.left.bottom.right.equalToSuperview().inset(containerInsets)
}
复制代码

通过这样的代码,绝大部分时候我们都可以只用一行代码去描述 view 跟 superview 之间的边距,而且修改起来也很方便。另外 CGPointCGSize 也遵循了这个协议,大家可以去挖掘更多有趣的用法,例如 size.equalTo(20)

修改约束时尽量使用 updateConstraints

原生的 NSLayoutConstraint 在使用时,如果我们需要修改 constant 的值,一般会使用一个变量去引用,有需要时再去通过这个引用修改它的 constant

同样的方式也适用于 SnapKit,我们可以通过 constraint 方法去获取到这个约束,然后强引用它:

var someConstraint: Constriant?

a.snp.makeConstriants {
    someConstraint = $0.top.equalToSuperview().constraint
    $0.left.equalToSuperview().inset(15)
    $0.bottom.equalToSuperview()
}
复制代码

但这种方式会让代码看起来很混乱,并且 topbottom 的约束必须拆成两行,一次性只能引用一个约束。更好的方式是使用 updateConstraints 方法:

a.snp.makeConstriants {
    $0.top.bottom.equalToSuperview()
    $0.left.equalToSuperview().inset(15)
}

...

a.snp.updateConstraints {
    $0.top.equalToSuperview().inset(10)
}
复制代码

这个方法会遍历现有的所有约束,然后找到你在 updateConstraints 里更新的约束,更新它们的 constant

这么做的好处就是语法更简洁一致,让约束表现得更像是 view 的属性。但缺点也很明显,只能更新 constant

小结

我个人感觉写好业务逻辑也不是一件容易的事情,但难度不是在于实现,而是可维护性跟实现速度,这里面还是有很多 best pratice 可以挖掘的。

觉得文章还不错的话可以关注一下我的博客

相关文章:

  • Linux的磁盘配额
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 100. bootstrap 弹出对话框bootbox.confirm
  • jetty的使用
  • mysql架构
  • 详解node.js中的可读流(Readable)和可写流(Writeable)
  • 一文看懂JeffDean等提出的ENAS到底好在哪?
  • MXNet 作者李沐:用深度学习做图像分类,教程+代码
  • Map集合、散列表、红黑树介绍
  • centos7.4系统的虚拟机网络配置教程
  • win10 php安装redis 扩展
  • 6、通过Appium Desktop 实现录制功能
  • 文件上传漏洞攻击
  • Micropython TPYBoard V10X拼插编程实践之定时器 代码不精通?...
  • 从抖音关闭评论,看服务治理的重要性
  • [译] 理解数组在 PHP 内部的实现(给PHP开发者的PHP源码-第四部分)
  • [译]CSS 居中(Center)方法大合集
  • 10个最佳ES6特性 ES7与ES8的特性
  • canvas 五子棋游戏
  • Linux后台研发超实用命令总结
  • mysql 5.6 原生Online DDL解析
  • PHP的类修饰符与访问修饰符
  • Swoft 源码剖析 - 代码自动更新机制
  • Transformer-XL: Unleashing the Potential of Attention Models
  • Vue组件定义
  • 飞驰在Mesos的涡轮引擎上
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 浮现式设计
  • 解决jsp引用其他项目时出现的 cannot be resolved to a type错误
  • 码农张的Bug人生 - 初来乍到
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 手写双向链表LinkedList的几个常用功能
  • 首页查询功能的一次实现过程
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 小程序button引导用户授权
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • ​secrets --- 生成管理密码的安全随机数​
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #100天计划# 2013年9月29日
  • #android不同版本废弃api,新api。
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (二)pulsar安装在独立的docker中,python测试
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (一)SpringBoot3---尚硅谷总结
  • (一)认识微服务
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • **PHP分步表单提交思路(分页表单提交)
  • ./configure,make,make install的作用(转)
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .NET Core跨平台微服务学习资源
  • .NET DevOps 接入指南 | 1. GitLab 安装
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NetCore部署微服务(二)