ConstraintAttributes篇
ConstraintAttributes结构体
结构体定义如下:
internal struct ConstraintAttributes: OptionSetType, BooleanType
一, 协议描述
ConstraintAttributes结构体实现了OptionSetType, BooleanType协议,这两个协议会继承其他的协议,其他协议不做介绍。有兴趣的同学可以点进源码查看。
OptionSetType协议
实现者可以增加如下功能:
- 类似位运算能力:
Widtn.rawValue | Height.rawValue == Size.rawValue
// 按位或 1<<6 | 1<<7 == 二进制表示为11000000
- 交集,并集,子集等系列数学处理功能.(我描述的不太准确):
例如在本结构体中的出现的应用点
internal var layoutAttributes:[NSLayoutAttribute] {
var attrs = [NSLayoutAttribute]()
//contains 解释为包含,个人理解: "&"(按位与)后值不等于0则为True,反之
//方法定义在是OptionSetType协议的扩展中
if (self.contains(ConstraintAttributes.Left)) {
attrs.append(.Left)
}
//..........
return attrs
}
//重写运算符
internal func +=(inout left: ConstraintAttributes, right: ConstraintAttributes) {
//unionInPlace 解释为合并 个人理解:取"|"(按位或)后的值
//unionInPlace定义在OptionSetType协议的扩展中
left.unionInPlace(right)
}
internal func -=(inout left: ConstraintAttributes, right: ConstraintAttributes) {
//subtractInPlace 解释为去除 个人理解:取"^"(按位异或)后的值
//subtractInPlace定义在OptionSetType协议的上级协议中
left.subtractInPlace(right)
}
- 原始值(rawValue)转换的能力
本结构体实例话后会对应rawValue , 在对该实例进行操作时,其实也是操作对应的rawValue。例如:
internal var layoutAttributes:[NSLayoutAttribute] {
var attrs = [NSLayoutAttribute]()
//操作ConstraintAttributes.Left实例其实就是操作对应的rawValue
if (self.contains(ConstraintAttributes.Left)) {
attrs.append(.Left)
}
//..........
return attrs
}
BooleanType协议
实现者可直接进行bool判断,例如在while , if 中
class BoolDemo: BooleanType{
var boolValue: Bool { return true } //实现协议属性
}
var bo = BoolDemo()
if(bo){
print("bo为true") //会输出打印结果
}
二, 大量的static实例变量是啥
本结构体中定义了大量的静态实例变量,get方法返回的都是”self”(很重要,返回的都是ConstraintAttributes类型实例,对应的rawValue不同)。这些实例变量是框架的基本粒子,在其他模块中会大量用到,所以声明为static,确保其一直存在(生命周期是一直存在?)。
internal static var None: ConstraintAttributes { return self.init(0) }
internal static var Left: ConstraintAttributes { return self.init(1) }
internal static var Top: ConstraintAttributes { return self.init(2) }
internal static var Right: ConstraintAttributes { return self.init(4) }
internal static var Bottom: ConstraintAttributes { return self.init(8) }
internal static var Leading: ConstraintAttributes { return self.init(16) }
internal static var Trailing: ConstraintAttributes { return self.init(32) }
internal static var Width: ConstraintAttributes { return self.init(64) }
internal static var Height: ConstraintAttributes { return self.init(128) }
//其他的就不粘了
这些实例变量与苹果原生的NSLayoutAttribute枚举一一对应。
public enum NSLayoutAttribute : Int {
case Left
case Right
case Top
case Bottom
case Leading
case Trailing
case Width
public static var LastBaseline: NSLayoutAttribute { get }
@available(iOS 8.0, *)
case TrailingMargin
@available(iOS 8.0, *)
case CenterXWithinMargins
@available(iOS 8.0, *)
case CenterYWithinMargins
case NotAnAttribute
//略了很多
}
还会多出如下实例变量。
internal static var Size: ConstraintAttributes { return self.init(192) }
internal static var Edges: ConstraintAttributes { return self.init(15) }
internal static var Center: ConstraintAttributes { return self.init(768) }
@available(iOS 8.0, *)
internal static var Margins: ConstraintAttributes { return self.init(61440) }
@available(iOS 8.0, *)
internal static var CenterWithinMargins: ConstraintAttributes { return self.init(786432) }
这些额外的实例变量在原生的NSLayoutAttribute枚举中是没有的,这也是SnapKit优秀的功能点。每一个额外的实例变量可以拆分成多个”与原生的NSLayoutAttribute枚举值相对应的实例变量”的组合。例如
- Size由Width和Height组合而成, Width的rawValue为Uint类型64(1<<6),Height的原始值定义为Uint类型128(1<<7) , (1<<6) | (1<<7) 按位或后二进制表示为11000000 也就是Uint类型192,192是Size的rawValue。
- Edges由Left,Right,Top,Bottom构成 Edges=Left | Right | Top | Bottom。
- Center和Margins,CenterWithMargins 同样适用。
三, 其他
layoutAttributes数组:
layoutAttributes数组的get方法 会先判断最后的rawValue值具体包含哪些ConstraintAttributes实例,并将这些ConstraintAttributes实例相对应的原生NSLayoutAttribute枚举类型保存到数组并返还。 最后的get到的值是构建原生NSLayoutConstraint所需参数。
internal var layoutAttributes:[NSLayoutAttribute] {
var attrs = [NSLayoutAttribute]()
if (self.contains(ConstraintAttributes.Left)) {
attrs.append(.Left)
}
if (self.contains(ConstraintAttributes.Top)) {
attrs.append(.Top)
}
if (self.contains(ConstraintAttributes.Right)) {
attrs.append(.Right)
}
if (self.contains(ConstraintAttributes.Bottom)) {
attrs.append(.Bottom)
}
if (self.contains(ConstraintAttributes.Leading)) {
attrs.append(.Leading)
}
if (self.contains(ConstraintAttributes.Trailing)) {
attrs.append(.Trailing)
}
//.......................
return attrs
}
框架关系中的角色:
本结构体(ConstraintAttributes)在整个框架中用于构建ConstraintItem实例。在其他模块中大量引用到。
调用指南
make.width.height.equalTo(50)
这段代码的.width(不要忽略”点”)和.height都会”调用”对应的Width,Height的实例,在执行过程中两者会进行+=操作(上面有重写+=运算符的代码),最后返还的是Size的rawValue值,Size包含了两者。
// "snp_topLayoutGuideTop","snp_height" 同样会分别调用"Top","Height"实例
make.top.equalTo(snp_topLayoutGuideTop)
make.width.equalTo(otherView.snp_height)
与构建 “原生NSLayoutConstraint ”对应位置关系:
public convenience init(
item view1: AnyObject,
attribute attr1: NSLayoutAttribute,
relatedBy relation: NSLayoutRelation,
attribute attr2: NSLayoutAttribute,
constant c: CGFloat)
对应原生构造方法中NSLayoutAttribute类型的参数。
注意!一个按位或后的rawValue会对应多个NSLayoutAttribute对象(例如Size对应Left和Right)。