SnapKit源码解读
什么是Snapkit
SnapKit是一个使用 Swift 编写而来的AutoLayout 框架,通过使用Snapkit,我们可以通过简短的代码完成布局,使用
view.snp.makeConstraints {
(make) in
make.center.equalToSuperview()
}
DSL(Domain specific Language)特定领域语言
DSL是为了解决某些特定场景下的任务而专门设计的语言。如果能把一些设计师产出的长宽、色值、文字、居中、距上等设计元数据(设计的标注信息等),以一种约定的简洁的语言规则(即DSL)输入给程序代码,由程序和代码自动的分析和处理,从而生成真正的界面开发代码setFrame,setTitle,setColor,addSubview,这样就可以大幅度的减少代码量与工作量,程序员来写这种简洁的语法规则会更快更高效,甚至可以把这种简洁的语法规则教会设计师,让设计师有能力直接写出DSL,然后输入给底层程序,这样界面就自然完成。
分析源码
lable.snp通过给view加扩展实现的
public extension ConstraintView {
public var snp: ConstraintViewDSL {
return ConstraintViewDSL(view: self
}
}
snp 最后是生成了一个 ConstraintViewDSL 对象
ConstraintView的定义
if os(iOS) || os(tvOS)
public typealias ConstraintView = UIView
#else public
typealias ConstraintView = NSView
#endif
这里,tvOS是基于 iOS的操作系统,tvOS 是专门为第四代 Apple TV设计的操作系统。
ConstraintViewDSL
internal init(view: ConstraintView) {
self.view = view
}
ConstraintViewDSL 类的构造函数,就是将 view 保存起来
public func makeConstraints(_ closure:
(_ make: ConstraintMaker) -> Void){
ConstraintMaker.makeConstraints(item:self.view, closure: closure)
}
makeConstraints 函数将传进来的闭包传递给ConstraintMaker 这个类去处理了
internal static func makeConstraints(item: LayoutConstraintItem,closure: (_ make: ConstraintMaker) -> Void) {
let constraints = prepareConstraints(item: item, closure: closure)
for constraint in constraints {
constraint.activateIfNeeded(updatingExisting: false)
}
}
该方法主要调用了被接受preConstraints函数。
internal static func prepareConstraints(item: LayoutConstraintItem, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
let maker = ConstraintMaker(item: item)
closure(maker)
var constraints: [Constraint] = []
for description in maker.descriptions {
guard let constraint = description.constraint else {
continue
}
constraints.append(constraint)
}
return constraints
}
首先这里构造一个 maker,然后调用闭包,闭包内部会添加一些约束,接下来就是获取这些约束, 最后将约束激活。
闭包就是能够读取其他函数内部变量的函数。例如在程序中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
internal init(item: LayoutConstraintItem) {
self.item = item
self.item.prepare()
}
这是ConstraintMaker的构造函数,这里出现了一个新的类型LayoutConstraintItem,表示一个可布局的对象,
public protocol LayoutConstraintItem: class {
}
可以看到这是一个协议
extension ConstraintLayoutGuide : LayoutConstraintItem {
}
extension ConstraintView : LayoutConstraintItem {
}
ConstraintView 和 ConstraintLayoutGuide 都实现LayoutConstraintItem这个协议。
extension LayoutConstraintItem {
internal func prepare() {