完美适配,您需要知道的 SnapKit

2,158 阅读3分钟

前言

众所周知,iPhone 的屏幕是越来越多样化了,多样化的屏幕满足了用户差异化的需求,同时也增加了开发者的工作 ----- 适配,面对多样化、不同屏幕尺寸的设备,之前在 iOS 中的 frame 布局以显得不合时宜,于是 Apple 推出了 AutoLayout ,AutoLayout 在可是化编程中的优势是不容置喙的,然而对于习惯于 code 界面的朋友来说就不那么友好了,面对这样的问题,众多第三方框架横空出世,目前为止支持率比较高的当属 SnapKit 了。

正文

当然,如果你之前对 Masonry 非常熟悉,那么恭喜你,你可以平滑的过度到 SnapKit, 如果你对 SnapKit 比较陌生,那么也没关系,请继续往下看☺。

安装

如果你的项目是用 CocoaPods 来管理组件的,那么你只需要在 Podfile 里加入 :

 pod 'SnapKit', '~> 3.0'

然后在 terminal 里执行

pod install

等待安装成功就可以 import SnapKit 使用了。

用法

SnapKit 框架的设计,简单易用,可读性好。当你想要构建一个 tableView , tableView 在父视图中的 padding 为 20, 那么用 SnapKit 怎么做呢?

tableView.snp.makeConstraints { (make) in
            make
                .edges
                .equalTo(self.view)
                .inset(UIEdgeInsets(
                    top: 20,
                    left: 20,
                    bottom: 20,
                    right: 20
                )
            )
        }

or

tableView.snp.makeConstraints { (make) in
            make.left.top.equalTo(self.view).offset(20)
            make.right.bottom.equalTo(self.view).offset(-20)
        }

这是最常用的写法了,当然我们的实际项目中的布局是非常复杂的,并不是所有的视图都能用 equalTo 来进行布局的,有了 SnapKit ,你可以用:

.equalTo 等价于 NSLayoutRelation.Equal .lessThanOrEqualTo 等价于 NSLayoutRelation.GreaterThanOrEqual .greaterThanOrEqualTo 等价于 NSLayoutRelation.GreaterThanOrEqual

我们用一张表来罗列出 SnapKit 的属性与 NSLayout 中的属性对应关系:

ViewAttribute NSLayoutAttribute
view.snp.left NSLayoutAttribute.left
view.snp.right NSLayoutAttribute.right
view.snp.top NSLayoutAttribute.top
view.snp.bottom NSLayoutAttribute.bottom
view.snp.leading NSLayoutAttribute.leading
view.snp.trailing NSLayoutAttribute.trailing
view.snp.width NSLayoutAttribute.width
view.snp.height NSLayoutAttribute.height
view.snp.centerX NSLayoutAttribute.centerX
view.snp.centerY NSLayoutAttribute.centerY
view.snp.lastBaseline NSLayoutAttribute.lastBaseline

通过这张表,我们可以根据自己的需要对相应的动画进行布局,但这还不能完全满足我们的需求,我们的应用是非常复杂的,如果产品要求我们的 APP 需要根据用户的交互反馈来更新视图的 frame 或者 需要做动画呢?别担心,SnapKit 为我们提供了 Constraint 属性关联。也就是说我们可以将要更改的约束进行关联,然后改变它,如: 声明关联属性

var topConstraint: Constraint? = nil

初始化

button.snp.makeConstraints { (make) in
            self.topConstraint = make.top.equalTo(self.view).offset(100).constraint
            make.centerX.equalTo(self.view.snp.centerX)
            make.width.equalTo(60)
            make.height.equalTo(30)
        }

更改

UIView.animate(withDuration: 5) {
            self.topConstraint?.update(offset: 200)
            self.view.layoutIfNeeded()
        }

这样一个简单的动画就完成了。当然,如果你想更新约束,你还可以用 .snp.updateConstraints

 self.button.snp.updateConstraints({ (make) in
                make.top.equalTo(200)
            })
            self.view.layoutIfNeeded()

还有一个问题是,如果我们引用了一个三方视图库,我们想改变他的约束,担忧不知道原来的约束怎么办呢?其实我们可以用 snp.remakeConstraints

        button.snp.remakeConstraints { (make) in
            make.top.equalTo(self.view).offset(100)
            make.centerX.equalTo(self.view.snp.centerX)
            make.width.equalTo(60)
            make.height.equalTo(30)
        }

这样首先会移除原有的控件的约束,然后重新设置约束。 看到这里相信大家对 SnapKit 的使用并不陌生了吧!

这里有一个常见的问题, 如果我们需要通过数组动态创建一组控件,要求长宽高都相等,并列排放在父视图中:

for (idx, item) in items.enumerated() {
            if items.count < 2 { return }
            if idx == 0 {
                item.snp.makeConstraints({ (make) in
                    make.left.top.bottom.equalTo(self)
                    make.width.equalTo(items[idx + 1])
                    make.right.equalTo(items[idx + 1].snp.left)
                })
            } else if idx == items.count - 1 {
                item.snp.makeConstraints({ (make) in
                    make.right.top.bottom.equalTo(self)
                    make.width.equalTo(items[idx - 1])
                })
            } else {
                item.snp.makeConstraints({ (make) in
                    make.top.bottom.equalTo(self)
                    make.left.equalTo(items[idx - 1].snp.right)
                    make.width.equalTo(items[idx - 1].snp.width)
                })
            }
        }

这样,一组动态的创建好了! 请看 AutoLayoutDemo 水平有限,如有疏漏,望指正 欢迎交流,欢迎 star CNKCQ 遗人🌹,手有余香 blog

参考

snapKit