首先UIView.snp是UIView扩展的计算属性,类型为ConstraintViewDSL(结构体).代码如下
public var snp: ConstraintViewDSL {
return ConstraintViewDSL(view: self)
}
常用的添加约束入口:
public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
ConstraintMaker.makeConstraints(item: self.view, closure: closure)
}
传入闭包closure, 用于收集各种约束, 具体由参数make: ConstraintMaker参与收集工作.
最终的收集处理工作由以下方法完成:
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
}
其中closure(maker), 就是调用我们我们从外界添加的各约束, 具体: maker.descriptions就是所有的约束描述(每一项属于类——ConstraintDescription),其中的每一项就是类似make.left.right.equalToSuperview()一行代码的约束。另一个关键的代码:description.constraint,这是一个计算属性,会构造类Constraint,而这个类又会在它的构造方法里生成最终系统能识别的约束类型——LayoutConstraint继承NSLayoutConstraint。
下面说说make.left.right.equalToSuperview()怎么收集单行的所有约束描述:
make属于ConstraintMaker,首先make会调用
public var left: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.left)
}
internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable {
let description = ConstraintDescription(item: self.item, attributes: attributes)
self.descriptions.append(description)
return ConstraintMakerExtendable(description)
}
left.right调用的是:
public var right: ConstraintMakerExtendable {
self.description.attributes += .right
return self
}
之后会返回类型ConstraintMakerExtendable,而我们看到约束描述是存储于ConstraintMaker.descriptions : [ConstraintDescription], 这时我们会有一个疑问: ConstraintMakerExtendable执行下一次(如.right)约束时怎么把约束保存到ConstraintMaker.descriptions, 其实很简单, 首先ConstraintMakerExtendable持有ConstraintDescription , ConstraintDescription是一个类, 所有约束都会保存到ConstraintDescription的实例对象, 而具体每一项存入ConstraintDescription.attributes. 对于每一行约束只会执行一次make.descriptions.append(description), 多行时make.descriptions才有多个值, 对于一行的其他约束执行ConstraintMakerExtendable.description.attributes += .right, ConstraintMakerExtendable.description.attributes 属于 结构体ConstraintAttributes, 这个结构体遵守OptionSet协议, 即是一个集合枚举类型能存储top bottom left right 等。