mirror of https://github.com/SnapKit/SnapKit
Merge branch 'develop'
This commit is contained in:
commit
f37b56b7a2
|
@ -1,4 +1,6 @@
|
||||||
project.xcworkspace
|
project.xcworkspace
|
||||||
xcuserdata
|
xcuserdata
|
||||||
Examples/
|
Examples/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
Gemfile
|
||||||
|
Gemfile.lock
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
Beta
|
Beta
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
# Next Release
|
||||||
|
|
||||||
|
* Re-worked some internal API to allow for future updates
|
||||||
|
* Added `snp_prepareConstraints -> [Constraint]` which allows pre-building of constraints
|
||||||
|
* Added a fatal error to `and` when it is used after relation has been set
|
||||||
|
|
||||||
# 0.0.6 - February 11th, 2015
|
# 0.0.6 - February 11th, 2015
|
||||||
|
|
||||||
* Renamed `maker` to `make` in all block APIs
|
* Renamed `maker` to `make` in all block APIs
|
|
@ -7,6 +7,8 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
EEAED5481A8F56A500777EF9 /* Snap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EEBCC9D819CC627D0083B827 /* Snap.framework */; };
|
||||||
|
EEAED5491A8F56BF00777EF9 /* SnapTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE91728C19CB304E007888CF /* SnapTests.swift */; };
|
||||||
EEBCC9F019CC64F80083B827 /* EdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCC9EF19CC64F70083B827 /* EdgeInsets.swift */; };
|
EEBCC9F019CC64F80083B827 /* EdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCC9EF19CC64F70083B827 /* EdgeInsets.swift */; };
|
||||||
EEBCC9F219CC65050083B827 /* View+Snap.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCC9F119CC65040083B827 /* View+Snap.swift */; };
|
EEBCC9F219CC65050083B827 /* View+Snap.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCC9F119CC65040083B827 /* View+Snap.swift */; };
|
||||||
EEBCC9F419CC65110083B827 /* ConstraintAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCC9F319CC65110083B827 /* ConstraintAttributes.swift */; };
|
EEBCC9F419CC65110083B827 /* ConstraintAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEBCC9F319CC65110083B827 /* ConstraintAttributes.swift */; };
|
||||||
|
@ -46,6 +48,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
EEAED5481A8F56A500777EF9 /* Snap.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -233,6 +236,7 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
EEAED5491A8F56BF00777EF9 /* SnapTests.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,19 +31,24 @@ import AppKit
|
||||||
* Constraint is a single item that defines all the properties for a single ConstraintMaker chain
|
* Constraint is a single item that defines all the properties for a single ConstraintMaker chain
|
||||||
*/
|
*/
|
||||||
public class Constraint {
|
public class Constraint {
|
||||||
public var left: Constraint { return addConstraint(ConstraintAttributes.Left) }
|
public var left: Constraint { return self.addConstraint(ConstraintAttributes.Left) }
|
||||||
public var top: Constraint { return addConstraint(ConstraintAttributes.Top) }
|
public var top: Constraint { return self.addConstraint(ConstraintAttributes.Top) }
|
||||||
public var right: Constraint { return addConstraint(ConstraintAttributes.Right) }
|
public var right: Constraint { return self.addConstraint(ConstraintAttributes.Right) }
|
||||||
public var bottom: Constraint { return addConstraint(ConstraintAttributes.Bottom) }
|
public var bottom: Constraint { return self.addConstraint(ConstraintAttributes.Bottom) }
|
||||||
public var leading: Constraint { return addConstraint(ConstraintAttributes.Leading) }
|
public var leading: Constraint { return self.addConstraint(ConstraintAttributes.Leading) }
|
||||||
public var trailing: Constraint { return addConstraint(ConstraintAttributes.Trailing) }
|
public var trailing: Constraint { return self.addConstraint(ConstraintAttributes.Trailing) }
|
||||||
public var width: Constraint { return addConstraint(ConstraintAttributes.Width) }
|
public var width: Constraint { return self.addConstraint(ConstraintAttributes.Width) }
|
||||||
public var height: Constraint { return addConstraint(ConstraintAttributes.Height) }
|
public var height: Constraint { return self.addConstraint(ConstraintAttributes.Height) }
|
||||||
public var centerX: Constraint { return addConstraint(ConstraintAttributes.CenterX) }
|
public var centerX: Constraint { return self.addConstraint(ConstraintAttributes.CenterX) }
|
||||||
public var centerY: Constraint { return addConstraint(ConstraintAttributes.CenterY) }
|
public var centerY: Constraint { return self.addConstraint(ConstraintAttributes.CenterY) }
|
||||||
public var baseline: Constraint { return addConstraint(ConstraintAttributes.Baseline) }
|
public var baseline: Constraint { return self.addConstraint(ConstraintAttributes.Baseline) }
|
||||||
|
|
||||||
public var and: Constraint { return self }
|
public var and: Constraint {
|
||||||
|
if self.relation != nil {
|
||||||
|
fatalError("And is semantic only and can only be used before a relation is set.")
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
public var with: Constraint { return self }
|
public var with: Constraint { return self }
|
||||||
|
|
||||||
// MARK: initializer
|
// MARK: initializer
|
||||||
|
@ -56,115 +61,115 @@ public class Constraint {
|
||||||
// MARK: equalTo
|
// MARK: equalTo
|
||||||
|
|
||||||
public func equalTo(other: ConstraintItem) -> Constraint {
|
public func equalTo(other: ConstraintItem) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: View) -> Constraint {
|
public func equalTo(other: View) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
public func equalTo(other: UILayoutSupport) -> Constraint {
|
public func equalTo(other: UILayoutSupport) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public func equalTo(other: Float) -> Constraint {
|
public func equalTo(other: Float) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: Double) -> Constraint {
|
public func equalTo(other: Double) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .Equal)
|
return self.constrainTo(Float(other), relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: CGFloat) -> Constraint {
|
public func equalTo(other: CGFloat) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .Equal)
|
return self.constrainTo(Float(other), relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: Int) -> Constraint {
|
public func equalTo(other: Int) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .Equal)
|
return self.constrainTo(Float(other), relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: UInt) -> Constraint {
|
public func equalTo(other: UInt) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .Equal)
|
return self.constrainTo(Float(other), relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: CGSize) -> Constraint {
|
public func equalTo(other: CGSize) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: CGPoint) -> Constraint {
|
public func equalTo(other: CGPoint) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
public func equalTo(other: EdgeInsets) -> Constraint {
|
public func equalTo(other: EdgeInsets) -> Constraint {
|
||||||
return constrainTo(other, relation: .Equal)
|
return self.constrainTo(other, relation: .Equal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: lessThanOrEqualTo
|
// MARK: lessThanOrEqualTo
|
||||||
|
|
||||||
public func lessThanOrEqualTo(other: ConstraintItem) -> Constraint {
|
public func lessThanOrEqualTo(other: ConstraintItem) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: View) -> Constraint {
|
public func lessThanOrEqualTo(other: View) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
public func lessThanOrEqualTo(other: UILayoutSupport) -> Constraint {
|
public func lessThanOrEqualTo(other: UILayoutSupport) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public func lessThanOrEqualTo(other: Float) -> Constraint {
|
public func lessThanOrEqualTo(other: Float) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: Double) -> Constraint {
|
public func lessThanOrEqualTo(other: Double) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: CGFloat) -> Constraint {
|
public func lessThanOrEqualTo(other: CGFloat) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: Int) -> Constraint {
|
public func lessThanOrEqualTo(other: Int) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: UInt) -> Constraint {
|
public func lessThanOrEqualTo(other: UInt) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: CGSize) -> Constraint {
|
public func lessThanOrEqualTo(other: CGSize) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: CGPoint) -> Constraint {
|
public func lessThanOrEqualTo(other: CGPoint) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func lessThanOrEqualTo(other: EdgeInsets) -> Constraint {
|
public func lessThanOrEqualTo(other: EdgeInsets) -> Constraint {
|
||||||
return constrainTo(other, relation: .LessThanOrEqualTo)
|
return self.constrainTo(other, relation: .LessThanOrEqualTo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: greaterThanOrEqualTo
|
// MARK: greaterThanOrEqualTo
|
||||||
|
|
||||||
public func greaterThanOrEqualTo(other: ConstraintItem) -> Constraint {
|
public func greaterThanOrEqualTo(other: ConstraintItem) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: View) -> Constraint {
|
public func greaterThanOrEqualTo(other: View) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
public func greaterThanOrEqualTo(other: UILayoutSupport) -> Constraint {
|
public func greaterThanOrEqualTo(other: UILayoutSupport) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public func greaterThanOrEqualTo(other: Float) -> Constraint {
|
public func greaterThanOrEqualTo(other: Float) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: Double) -> Constraint {
|
public func greaterThanOrEqualTo(other: Double) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: CGFloat) -> Constraint {
|
public func greaterThanOrEqualTo(other: CGFloat) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: Int) -> Constraint {
|
public func greaterThanOrEqualTo(other: Int) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: UInt) -> Constraint {
|
public func greaterThanOrEqualTo(other: UInt) -> Constraint {
|
||||||
return constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: CGSize) -> Constraint {
|
public func greaterThanOrEqualTo(other: CGSize) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: CGPoint) -> Constraint {
|
public func greaterThanOrEqualTo(other: CGPoint) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
public func greaterThanOrEqualTo(other: EdgeInsets) -> Constraint {
|
public func greaterThanOrEqualTo(other: EdgeInsets) -> Constraint {
|
||||||
return constrainTo(other, relation: .GreaterThanOrEqualTo)
|
return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: multiplier
|
// MARK: multiplier
|
||||||
|
@ -282,11 +287,6 @@ public class Constraint {
|
||||||
// MARK: internal
|
// MARK: internal
|
||||||
|
|
||||||
internal func installOnView(updateExisting: Bool = false) -> Array<LayoutConstraint> {
|
internal func installOnView(updateExisting: Bool = false) -> Array<LayoutConstraint> {
|
||||||
if self.installedOnView != nil {
|
|
||||||
NSException(name: "Cannot Install Constraint", reason: "Already installed", userInfo: nil).raise()
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
var installOnView: View? = nil
|
var installOnView: View? = nil
|
||||||
if self.toItem.view != nil {
|
if self.toItem.view != nil {
|
||||||
installOnView = Constraint.closestCommonSuperviewFromView(self.fromItem.view, toView: self.toItem.view)
|
installOnView = Constraint.closestCommonSuperviewFromView(self.fromItem.view, toView: self.toItem.view)
|
||||||
|
@ -301,14 +301,22 @@ public class Constraint {
|
||||||
installOnView = self.fromItem.view
|
installOnView = self.fromItem.view
|
||||||
}
|
}
|
||||||
|
|
||||||
if installedOnView == nil {
|
if installOnView == nil {
|
||||||
NSException(name: "Cannot Install Constraint", reason: "Missing superview", userInfo: nil).raise()
|
NSException(name: "Cannot Install Constraint", reason: "Missing superview", userInfo: nil).raise()
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var layoutConstraints: Array<LayoutConstraint> = []
|
if self.installedOnView != nil {
|
||||||
|
if self.installedOnView != installOnView {
|
||||||
|
NSException(name: "Cannot Install Constraint", reason: "Already installed on different view.", userInfo: nil).raise()
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return self.installedLayoutConstraints?.allObjects as Array<LayoutConstraint>
|
||||||
|
}
|
||||||
|
|
||||||
|
var newLayoutConstraints = Array<LayoutConstraint>()
|
||||||
let layoutFromAttributes = self.fromItem.attributes.layoutAttributes
|
let layoutFromAttributes = self.fromItem.attributes.layoutAttributes
|
||||||
let layoutToAttributes = self.toItem.attributes.layoutAttributes
|
let layoutToAttributes = self.toItem.attributes.layoutAttributes
|
||||||
|
|
||||||
|
@ -348,7 +356,7 @@ public class Constraint {
|
||||||
// set constraint
|
// set constraint
|
||||||
layoutConstraint.constraint = self
|
layoutConstraint.constraint = self
|
||||||
|
|
||||||
layoutConstraints.append(layoutConstraint)
|
newLayoutConstraints.append(layoutConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
// special logic for updating
|
// special logic for updating
|
||||||
|
@ -356,11 +364,11 @@ public class Constraint {
|
||||||
// get existing constraints for this view
|
// get existing constraints for this view
|
||||||
let existingLayoutConstraints = reverse(layoutFrom!.snp_installedLayoutConstraints)
|
let existingLayoutConstraints = reverse(layoutFrom!.snp_installedLayoutConstraints)
|
||||||
|
|
||||||
// array that will contain only new layout constraints
|
// array that will contain only new layout constraints to keep
|
||||||
var newLayoutConstraints = Array<LayoutConstraint>()
|
var newLayoutConstraintsToKeep = Array<LayoutConstraint>()
|
||||||
|
|
||||||
// begin looping
|
// begin looping
|
||||||
for layoutConstraint in layoutConstraints {
|
for layoutConstraint in newLayoutConstraints {
|
||||||
// layout constraint that should be updated
|
// layout constraint that should be updated
|
||||||
var updateLayoutConstraint: LayoutConstraint? = nil
|
var updateLayoutConstraint: LayoutConstraint? = nil
|
||||||
|
|
||||||
|
@ -376,34 +384,45 @@ public class Constraint {
|
||||||
if updateLayoutConstraint != nil {
|
if updateLayoutConstraint != nil {
|
||||||
updateLayoutConstraint!.constant = layoutConstraint.constant
|
updateLayoutConstraint!.constant = layoutConstraint.constant
|
||||||
}
|
}
|
||||||
// otherwise add this layout constraint to new list
|
// otherwise add this layout constraint to new keep list
|
||||||
else {
|
else {
|
||||||
newLayoutConstraints.append(layoutConstraint)
|
newLayoutConstraintsToKeep.append(layoutConstraint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set constraints to only new ones
|
// set constraints to only new ones
|
||||||
layoutConstraints = newLayoutConstraints
|
newLayoutConstraints = newLayoutConstraintsToKeep
|
||||||
}
|
}
|
||||||
|
|
||||||
// add constraints
|
// add constraints
|
||||||
installOnView!.addConstraints(layoutConstraints)
|
installOnView!.addConstraints(newLayoutConstraints)
|
||||||
|
|
||||||
|
// store which view this constraint was installed on
|
||||||
self.installedOnView = installOnView
|
self.installedOnView = installOnView
|
||||||
|
|
||||||
|
// store which layout constraints are installed for this constraint
|
||||||
self.installedLayoutConstraints = NSHashTable.weakObjectsHashTable()
|
self.installedLayoutConstraints = NSHashTable.weakObjectsHashTable()
|
||||||
for layoutConstraint in layoutConstraints {
|
for layoutConstraint in newLayoutConstraints {
|
||||||
self.installedLayoutConstraints!.addObject(layoutConstraint)
|
self.installedLayoutConstraints!.addObject(layoutConstraint)
|
||||||
}
|
}
|
||||||
|
|
||||||
return layoutConstraints
|
// store the layout constraints against the installed on view
|
||||||
|
var layoutConstraints = Array<LayoutConstraint>(layoutFrom!.snp_installedLayoutConstraints)
|
||||||
|
layoutConstraints += newLayoutConstraints
|
||||||
|
layoutFrom!.snp_installedLayoutConstraints = layoutConstraints
|
||||||
|
|
||||||
|
// return the new constraints
|
||||||
|
return newLayoutConstraints
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func uninstallFromView() {
|
internal func uninstallFromView() {
|
||||||
if let view = self.installedOnView {
|
if let view = self.installedOnView {
|
||||||
// remove all installed layout constraints
|
// remove all installed layout constraints
|
||||||
var layoutConstraintsToRemove = Array<LayoutConstraint>()
|
var layoutConstraintsToRemove = Array<LayoutConstraint>()
|
||||||
if let installedLayoutConstraints = self.installedLayoutConstraints?.allObjects as? Array<LayoutConstraint> {
|
if let allObjects = self.installedLayoutConstraints?.allObjects {
|
||||||
layoutConstraintsToRemove += installedLayoutConstraints
|
if let installedLayoutConstraints = allObjects as? Array<LayoutConstraint> {
|
||||||
|
layoutConstraintsToRemove += installedLayoutConstraints
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if layoutConstraintsToRemove.count > 0 {
|
if layoutConstraintsToRemove.count > 0 {
|
||||||
|
@ -490,19 +509,27 @@ public class Constraint {
|
||||||
}
|
}
|
||||||
|
|
||||||
private class func closestCommonSuperviewFromView(fromView: View?, toView: View?) -> View? {
|
private class func closestCommonSuperviewFromView(fromView: View?, toView: View?) -> View? {
|
||||||
var closestCommonSuperview: View?
|
var views = NSMutableSet()
|
||||||
var secondViewSuperview: View? = toView
|
var fromView = fromView
|
||||||
while closestCommonSuperview == nil && secondViewSuperview != nil {
|
var toView = toView
|
||||||
var firstViewSuperview = fromView
|
do {
|
||||||
while closestCommonSuperview == nil && firstViewSuperview != nil {
|
if let view = toView {
|
||||||
if secondViewSuperview == firstViewSuperview {
|
if views.containsObject(view) {
|
||||||
closestCommonSuperview = secondViewSuperview
|
return view
|
||||||
}
|
}
|
||||||
firstViewSuperview = firstViewSuperview?.superview
|
views.addObject(view)
|
||||||
|
toView = view.superview
|
||||||
}
|
}
|
||||||
secondViewSuperview = secondViewSuperview?.superview
|
if let view = fromView {
|
||||||
}
|
if views.containsObject(view) {
|
||||||
return closestCommonSuperview
|
return view
|
||||||
|
}
|
||||||
|
views.addObject(view)
|
||||||
|
fromView = view.superview
|
||||||
|
}
|
||||||
|
} while (fromView != nil || toView != nil)
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,21 +31,21 @@ import AppKit
|
||||||
* ConstraintMaker is the maker in snap that gets all constraints kickstarted
|
* ConstraintMaker is the maker in snap that gets all constraints kickstarted
|
||||||
*/
|
*/
|
||||||
public class ConstraintMaker {
|
public class ConstraintMaker {
|
||||||
public var left: Constraint { return addConstraint(ConstraintAttributes.Left) }
|
public var left: Constraint { return self.addConstraint(ConstraintAttributes.Left) }
|
||||||
public var top: Constraint { return addConstraint(ConstraintAttributes.Top) }
|
public var top: Constraint { return self.addConstraint(ConstraintAttributes.Top) }
|
||||||
public var right: Constraint { return addConstraint(ConstraintAttributes.Right) }
|
public var right: Constraint { return self.addConstraint(ConstraintAttributes.Right) }
|
||||||
public var bottom: Constraint { return addConstraint(ConstraintAttributes.Bottom) }
|
public var bottom: Constraint { return self.addConstraint(ConstraintAttributes.Bottom) }
|
||||||
public var leading: Constraint { return addConstraint(ConstraintAttributes.Leading) }
|
public var leading: Constraint { return self.addConstraint(ConstraintAttributes.Leading) }
|
||||||
public var trailing: Constraint { return addConstraint(ConstraintAttributes.Trailing) }
|
public var trailing: Constraint { return self.addConstraint(ConstraintAttributes.Trailing) }
|
||||||
public var width: Constraint { return addConstraint(ConstraintAttributes.Width) }
|
public var width: Constraint { return self.addConstraint(ConstraintAttributes.Width) }
|
||||||
public var height: Constraint { return addConstraint(ConstraintAttributes.Height) }
|
public var height: Constraint { return self.addConstraint(ConstraintAttributes.Height) }
|
||||||
public var centerX: Constraint { return addConstraint(ConstraintAttributes.CenterX) }
|
public var centerX: Constraint { return self.addConstraint(ConstraintAttributes.CenterX) }
|
||||||
public var centerY: Constraint { return addConstraint(ConstraintAttributes.CenterY) }
|
public var centerY: Constraint { return self.addConstraint(ConstraintAttributes.CenterY) }
|
||||||
public var baseline: Constraint { return addConstraint(ConstraintAttributes.Baseline) }
|
public var baseline: Constraint { return self.addConstraint(ConstraintAttributes.Baseline) }
|
||||||
|
|
||||||
public var edges: Constraint { return addConstraint(ConstraintAttributes.Edges) }
|
public var edges: Constraint { return self.addConstraint(ConstraintAttributes.Edges) }
|
||||||
public var size: Constraint { return addConstraint(ConstraintAttributes.Size) }
|
public var size: Constraint { return self.addConstraint(ConstraintAttributes.Size) }
|
||||||
public var center: Constraint { return addConstraint(ConstraintAttributes.Center) }
|
public var center: Constraint { return self.addConstraint(ConstraintAttributes.Center) }
|
||||||
|
|
||||||
init(view: View) {
|
init(view: View) {
|
||||||
self.view = view
|
self.view = view
|
||||||
|
@ -61,24 +61,26 @@ public class ConstraintMaker {
|
||||||
return constraint
|
return constraint
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class func makeConstraints(view: View, block: (make: ConstraintMaker) -> ()) {
|
internal class func prepareConstraints(view: View, block: (make: ConstraintMaker) -> Void) -> Array<Constraint> {
|
||||||
#if os(iOS)
|
|
||||||
view.setTranslatesAutoresizingMaskIntoConstraints(false)
|
|
||||||
#else
|
|
||||||
view.translatesAutoresizingMaskIntoConstraints = false
|
|
||||||
#endif
|
|
||||||
let maker = ConstraintMaker(view: view)
|
let maker = ConstraintMaker(view: view)
|
||||||
block(make: maker)
|
block(make: maker)
|
||||||
|
return maker.constraints
|
||||||
var layoutConstraints = view.snp_installedLayoutConstraints
|
|
||||||
for constraint in maker.constraints {
|
|
||||||
layoutConstraints += constraint.install()
|
|
||||||
}
|
|
||||||
|
|
||||||
view.snp_installedLayoutConstraints = layoutConstraints
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class func remakeConstraints(view: View, block: (make: ConstraintMaker) -> ()) {
|
internal class func makeConstraints(view: View, block: (make: ConstraintMaker) -> Void) {
|
||||||
|
#if os(iOS)
|
||||||
|
view.setTranslatesAutoresizingMaskIntoConstraints(false)
|
||||||
|
#else
|
||||||
|
view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
#endif
|
||||||
|
let maker = ConstraintMaker(view: view)
|
||||||
|
block(make: maker)
|
||||||
|
for constraint in maker.constraints {
|
||||||
|
constraint.installOnView(updateExisting: false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class func remakeConstraints(view: View, block: (make: ConstraintMaker) -> Void) {
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
view.setTranslatesAutoresizingMaskIntoConstraints(false)
|
view.setTranslatesAutoresizingMaskIntoConstraints(false)
|
||||||
#else
|
#else
|
||||||
|
@ -87,20 +89,17 @@ public class ConstraintMaker {
|
||||||
let maker = ConstraintMaker(view: view)
|
let maker = ConstraintMaker(view: view)
|
||||||
block(make: maker)
|
block(make: maker)
|
||||||
|
|
||||||
var layoutConstraints: Array<LayoutConstraint> = view.snp_installedLayoutConstraints
|
var layoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
|
||||||
for existingLayoutConstraint in layoutConstraints {
|
for existingLayoutConstraint in layoutConstraints {
|
||||||
existingLayoutConstraint.constraint?.uninstall()
|
existingLayoutConstraint.constraint?.uninstallFromView()
|
||||||
}
|
}
|
||||||
layoutConstraints = []
|
|
||||||
|
|
||||||
for constraint in maker.constraints {
|
for constraint in maker.constraints {
|
||||||
layoutConstraints += constraint.install()
|
constraint.installOnView(updateExisting: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
view.snp_installedLayoutConstraints = layoutConstraints
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class func updateConstraints(view: View, block: (make: ConstraintMaker) -> ()) {
|
internal class func updateConstraints(view: View, block: (make: ConstraintMaker) -> Void) {
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
view.setTranslatesAutoresizingMaskIntoConstraints(false)
|
view.setTranslatesAutoresizingMaskIntoConstraints(false)
|
||||||
#else
|
#else
|
||||||
|
@ -109,19 +108,15 @@ public class ConstraintMaker {
|
||||||
let maker = ConstraintMaker(view: view)
|
let maker = ConstraintMaker(view: view)
|
||||||
block(make: maker)
|
block(make: maker)
|
||||||
|
|
||||||
var layoutConstraints = view.snp_installedLayoutConstraints
|
|
||||||
for constraint in maker.constraints {
|
for constraint in maker.constraints {
|
||||||
layoutConstraints += constraint.installOnView(updateExisting: true)
|
constraint.installOnView(updateExisting: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
view.snp_installedLayoutConstraints = layoutConstraints
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class func removeConstraints(view: View) {
|
internal class func removeConstraints(view: View) {
|
||||||
for existingLayoutConstraint in view.snp_installedLayoutConstraints {
|
let existingLayoutConstraints = Array<LayoutConstraint>(view.snp_installedLayoutConstraints)
|
||||||
existingLayoutConstraint.constraint?.uninstall()
|
for existingLayoutConstraint in existingLayoutConstraints {
|
||||||
|
existingLayoutConstraint.constraint?.uninstallFromView()
|
||||||
}
|
}
|
||||||
|
|
||||||
view.snp_installedLayoutConstraints = []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -68,15 +68,19 @@ public extension View {
|
||||||
public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) }
|
public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public func snp_makeConstraints(block: (make: ConstraintMaker) -> ()) {
|
public func snp_prepareConstraints(block: (make: ConstraintMaker) -> Void) -> Array<Constraint> {
|
||||||
|
return ConstraintMaker.prepareConstraints(self, block: block)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func snp_makeConstraints(block: (make: ConstraintMaker) -> Void) {
|
||||||
ConstraintMaker.makeConstraints(self, block: block)
|
ConstraintMaker.makeConstraints(self, block: block)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func snp_updateConstraints(block: (make: ConstraintMaker) -> ()) {
|
public func snp_updateConstraints(block: (make: ConstraintMaker) -> Void) {
|
||||||
ConstraintMaker.updateConstraints(self, block: block)
|
ConstraintMaker.updateConstraints(self, block: block)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func snp_remakeConstraints(block: (make: ConstraintMaker) -> ()) {
|
public func snp_remakeConstraints(block: (make: ConstraintMaker) -> Void) {
|
||||||
ConstraintMaker.remakeConstraints(self, block: block)
|
ConstraintMaker.remakeConstraints(self, block: block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,11 +92,10 @@ public extension View {
|
||||||
|
|
||||||
internal var snp_installedLayoutConstraints: Array<LayoutConstraint> {
|
internal var snp_installedLayoutConstraints: Array<LayoutConstraint> {
|
||||||
get {
|
get {
|
||||||
var constraints = objc_getAssociatedObject(self, &installedLayoutConstraintsKey) as? Array<LayoutConstraint>
|
if let constraints = objc_getAssociatedObject(self, &installedLayoutConstraintsKey) as? Array<LayoutConstraint> {
|
||||||
if constraints != nil {
|
return constraints
|
||||||
return constraints!
|
|
||||||
}
|
}
|
||||||
return []
|
return Array<LayoutConstraint>()
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
objc_setAssociatedObject(self, &installedLayoutConstraintsKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
|
objc_setAssociatedObject(self, &installedLayoutConstraintsKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
|
||||||
|
|
|
@ -8,9 +8,12 @@
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import XCTest
|
import XCTest
|
||||||
|
import Snap
|
||||||
|
|
||||||
class SnapTests: XCTestCase {
|
class SnapTests: XCTestCase {
|
||||||
|
|
||||||
|
let container = UIView()
|
||||||
|
|
||||||
override func setUp() {
|
override func setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||||
|
@ -21,16 +24,146 @@ class SnapTests: XCTestCase {
|
||||||
super.tearDown()
|
super.tearDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testExample() {
|
func testMakeConstraints() {
|
||||||
// This is an example of a functional test case.
|
let v1 = UIView()
|
||||||
XCTAssert(true, "Pass")
|
let v2 = UIView()
|
||||||
|
self.container.addSubview(v1)
|
||||||
|
self.container.addSubview(v2)
|
||||||
|
|
||||||
|
v1.snp_makeConstraints { (make) -> Void in
|
||||||
|
make.top.equalTo(v2.snp_top).offset(50)
|
||||||
|
make.left.equalTo(v2.snp_top).offset(50)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 2, "Should have 2 constraints installed")
|
||||||
|
|
||||||
|
v2.snp_makeConstraints { (make) -> Void in
|
||||||
|
make.edges.equalTo(v1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 6, "Should have 6 constraints installed")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testPerformanceExample() {
|
func testUpdateConstraints() {
|
||||||
// This is an example of a performance test case.
|
let v1 = UIView()
|
||||||
self.measureBlock() {
|
let v2 = UIView()
|
||||||
// Put the code you want to measure the time of here.
|
self.container.addSubview(v1)
|
||||||
|
self.container.addSubview(v2)
|
||||||
|
|
||||||
|
v1.snp_makeConstraints { (make) -> Void in
|
||||||
|
make.top.equalTo(v2.snp_top).offset(50)
|
||||||
|
make.left.equalTo(v2.snp_top).offset(50)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 2, "Should have 2 constraints installed")
|
||||||
|
|
||||||
|
v1.snp_updateConstraints { (make) -> Void in
|
||||||
|
make.top.equalTo(v2.snp_top).offset(15)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 2, "Should still have 2 constraints installed")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRemakeConstraints() {
|
||||||
|
let v1 = UIView()
|
||||||
|
let v2 = UIView()
|
||||||
|
self.container.addSubview(v1)
|
||||||
|
self.container.addSubview(v2)
|
||||||
|
|
||||||
|
v1.snp_makeConstraints { (make) -> Void in
|
||||||
|
make.top.equalTo(v2.snp_top).offset(50)
|
||||||
|
make.left.equalTo(v2.snp_top).offset(50)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 2, "Should have 2 constraints installed")
|
||||||
|
|
||||||
|
v1.snp_remakeConstraints { (make) -> Void in
|
||||||
|
make.edges.equalTo(v2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 4, "Should have 4 constraints installed")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRemoveConstraints() {
|
||||||
|
let v1 = UIView()
|
||||||
|
let v2 = UIView()
|
||||||
|
self.container.addSubview(v1)
|
||||||
|
self.container.addSubview(v2)
|
||||||
|
|
||||||
|
v1.snp_makeConstraints { (make) -> Void in
|
||||||
|
make.top.equalTo(v2.snp_top).offset(50)
|
||||||
|
make.left.equalTo(v2.snp_top).offset(50)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 2, "Should have 2 constraints installed")
|
||||||
|
|
||||||
|
v1.snp_removeConstraints()
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 0, "Should have 0 constraints installed")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPrepareConstraints() {
|
||||||
|
let v1 = UIView()
|
||||||
|
let v2 = UIView()
|
||||||
|
self.container.addSubview(v1)
|
||||||
|
self.container.addSubview(v2)
|
||||||
|
|
||||||
|
let constraints = v1.snp_prepareConstraints { (make) -> Void in
|
||||||
|
make.edges.equalTo(v2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 0, "Should have 0 constraints installed")
|
||||||
|
|
||||||
|
for constraint in constraints {
|
||||||
|
constraint.install()
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 4, "Should have 4 constraints installed")
|
||||||
|
|
||||||
|
for constraint in constraints {
|
||||||
|
constraint.uninstall()
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 0, "Should have 0 constraints installed")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func testReinstallConstraints() {
|
||||||
|
let v1 = UIView()
|
||||||
|
let v2 = UIView()
|
||||||
|
self.container.addSubview(v1)
|
||||||
|
self.container.addSubview(v2)
|
||||||
|
|
||||||
|
let constraints = v1.snp_prepareConstraints { (make) -> Void in
|
||||||
|
make.edges.equalTo(v2)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 0, "Should have 0 constraints installed")
|
||||||
|
|
||||||
|
for constraint in constraints {
|
||||||
|
constraint.install()
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 4, "Should have 4 constraints installed")
|
||||||
|
|
||||||
|
for constraint in constraints {
|
||||||
|
constraint.install()
|
||||||
|
}
|
||||||
|
|
||||||
|
XCTAssertEqual(self.container.constraints().count, 4, "Should have 0 constraints installed")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue