SnapKit 约束创建过程

创建ConstraintViewDSL
调用UIView
的 snp
方法,生成一个ConstraintViewDSL
。
注意这个生成的ConstraintViewDSL
持有UIView
。
创建ConstraintMaker
调用makeConstraints
,调用ConstraintMaker
对应的静态方法。
在方法的实现中,创建一个ConstraintMaker
。
注意这个ConstraintMaker
,持有UIView
。
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
}
调用闭包中的方法,生成ConstraintMakerRelatable
在调用snp.left
等方法时,会调用makeExtendableWithAttributes()
生成 ConstraintMakerExtendable
实例。
public var left: ConstraintMakerExtendable {
return self.makeExtendableWithAttributes(.left)
}
在makeExtendableWithAttributes()
方法中,会生成ConstraintDescription
,并被加到ConstraintMaker
的一个数组中。
internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable {
let description = ConstraintDescription(item: self.item, attributes: attributes)
self.descriptions.append(description)
return ConstraintMakerExtendable(description)
}
在ConstraintMakerRelatable
中,完善约束的属性信息
ConstraintMakerExtendable
是ConstraintMakerRelatable
的子类。
这两个类要提供的信息是哪个View
的什么属性要和哪个View
的什么属性产生联系
public class ConstraintMakerExtendable: ConstraintMakerRelatable {
// 完善from 的属性信息
public var left: ConstraintMakerExtendable {
self.description.attributes += .left
return self
}
...
}
public class ConstraintMakerRelatable {
internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable {
...
let editable = ConstraintMakerEditable(self.description)
editable.description.sourceLocation = (file, line)
// 约束信息的目标对象
editable.description.relation = relation
editable.description.related = related
editable.description.constant = constant
}
}
在ConstraintMakerFinalizable
类中,完善约束细节
ConstraintMakerEditable
->ConstraintMakerPriortizable
->ConstraintMakerFinalizable
这三个类分别细化约束的具体数值、优先级、标签。
public class ConstraintMakerFinalizable {
...
public var constraint: Constraint {
return self.description.constraint!
}
...
}
可以通过constraint
方法,生成真实需要的约束。
内存问题
上面提到的类,都是生成约束过程中用到的,生成约束以后,就都销毁了。
生成的约束,被UIView
持有,最终在内存中的,也只有Constraint
这个属性以及它持有的其他属性。
Constraint 被 UIView 持有

可以看到Constraint
被加在了一个Set
中,

而这个Set
是约束被加到UIView
中时,第一次取Set
时,被初始化的。
Constraint
持有 ConstraintItem


即from
和to
属性
ConstraintItem
通过weak
持有 UIView
public final class ConstraintItem {
internal weak var target: AnyObject?
internal let attributes: ConstraintAttributes
}
通过打印,也可以看到这一点。
(lldb) po blueView
<UIView: 0x7fe47bf998b0; frame = (0 0; 0 0); layer = <CALayer: 0x7fe47bf96fb0>>
(lldb) po blueView.constraintsa.first!.from.target
▿ Optional<AnyObject>
- some : <UIView: 0x7fe47bf998b0; frame = (0 0; 0 0); layer = <CALayer: 0x7fe47bf96fb0>>