diff --git a/SnapKit.xcodeproj/project.pbxproj b/SnapKit.xcodeproj/project.pbxproj index 4cbdd63..31ba47f 100644 --- a/SnapKit.xcodeproj/project.pbxproj +++ b/SnapKit.xcodeproj/project.pbxproj @@ -507,6 +507,7 @@ EEBCC9E119CC627D0083B827 = { CreatedOnToolsVersion = 6.0; LastSwiftMigration = 0800; + ProvisioningStyle = Automatic; }; EECDB3791AC0C9D4006BBC11 = { CreatedOnToolsVersion = 6.2; @@ -945,7 +946,8 @@ EEBCC9EC19CC627E0083B827 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "io.snapkit.$(PRODUCT_NAME:rfc1034identifier)"; @@ -957,7 +959,8 @@ EEBCC9ED19CC627E0083B827 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = "$(inherited)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/Tests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "io.snapkit.$(PRODUCT_NAME:rfc1034identifier)"; diff --git a/Source/Constraint.swift b/Source/Constraint.swift index 310c8e2..b1d4c03 100644 --- a/Source/Constraint.swift +++ b/Source/Constraint.swift @@ -27,10 +27,10 @@ import AppKit #endif - public class Constraint { internal let sourceLocation: (String, UInt) + internal let label: String? private let from: ConstraintItem private let to: ConstraintItem @@ -46,7 +46,7 @@ public class Constraint { self.updateConstantAndPriorityIfNeeded() } } - private var installInfo: ConstraintInstallInfo? = nil + private let layoutConstraints: NSHashTable // MARK: Initialization @@ -54,6 +54,7 @@ public class Constraint { to: ConstraintItem, relation: ConstraintRelation, sourceLocation: (String, UInt), + label: String?, multiplier: ConstraintMultiplierTarget, constant: ConstraintConstantTarget, priority: ConstraintPriorityTarget) { @@ -61,27 +62,67 @@ public class Constraint { self.to = to self.relation = relation self.sourceLocation = sourceLocation + self.label = label self.multiplier = multiplier self.constant = constant self.priority = priority + self.layoutConstraints = NSHashTable.weakObjects() + + // get attributes + let layoutFromAttributes = self.from.attributes.layoutAttributes + let layoutToAttributes = self.to.attributes.layoutAttributes + + // get layout from + let layoutFrom: ConstraintView = self.from.view! + + // get relation + let layoutRelation = self.relation.layoutRelation + + for layoutFromAttribute in layoutFromAttributes { + // get layout to attribute + let layoutToAttribute = (layoutToAttributes.count > 0) ? layoutToAttributes[0] : layoutFromAttribute + + // get layout constant + let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute) + + // get layout to + #if os(iOS) || os(tvOS) + let layoutTo: AnyObject? = self.to.view ?? self.to.layoutSupport + #else + let layoutTo: AnyObject? = self.to.view + #endif + + // create layout constraint + let layoutConstraint = LayoutConstraint( + item: layoutFrom, + attribute: layoutFromAttribute, + relatedBy: layoutRelation, + toItem: layoutTo, + attribute: layoutToAttribute, + multiplier: self.multiplier.constraintMultiplierTargetValue, + constant: layoutConstant + ) + + // set label + layoutConstraint.label = self.label + + // set priority + layoutConstraint.priority = self.priority.constraintPriorityTargetValue + + // set constraint + layoutConstraint.constraint = self + + // append + self.layoutConstraints.add(layoutConstraint) + } } // MARK: Public - public func install() -> [NSLayoutConstraint] { - return self.installIfNeeded(updateExisting: false) - } - - public func uninstall() { - self.uninstallIfNeeded() - } - - @available(iOS 8.0, OSX 10.10, *) public func activate() { self.activateIfNeeded() } - @available(iOS 8.0, OSX 10.10, *) public func deactivate() { self.deactivateIfNeeded() } @@ -128,248 +169,55 @@ public class Constraint { // MARK: Internal internal func updateConstantAndPriorityIfNeeded() { - guard let installInfo = self.installInfo else { - return - } - for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] { + for layoutConstraint in self.layoutConstraints.allObjects { let attribute = (layoutConstraint.secondAttribute == .notAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute layoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: attribute) layoutConstraint.priority = self.priority.constraintPriorityTargetValue } } - internal func installIfNeeded(updateExisting: Bool = false) -> [NSLayoutConstraint] { - let installOnView: ConstraintView? + internal func activateIfNeeded(updatingExisting: Bool = false) { + let view = self.from.view! + let layoutConstraints = self.layoutConstraints.allObjects + let existingLayoutConstraints = view.snp.layoutConstraints - if let view = self.to.view { - guard let closestSuperview = closestCommonSuperviewFromView(self.from.view, toView: view) else { - fatalError("Cannot Install Constraint. No common superview. (\(self.sourceLocation.0), \(self.sourceLocation.1))") + if updatingExisting && existingLayoutConstraints.count > 0 { + + for layoutConstraint in layoutConstraints { + let existingLayoutConstraint = existingLayoutConstraints.first { $0 == layoutConstraint } + guard let updateLayoutConstraint = existingLayoutConstraint else { + fatalError("Updated constraint could not find existing matching constraint to update: \(layoutConstraint)") + } + + let updateLayoutAttribute = (updateLayoutConstraint.secondAttribute == .notAnAttribute) ? updateLayoutConstraint.firstAttribute : updateLayoutConstraint.secondAttribute + updateLayoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: updateLayoutAttribute) } - installOnView = closestSuperview - } else if self.from.attributes.isSubset(of: ConstraintAttributes.Width + ConstraintAttributes.Height) { - installOnView = self.from.view + } else { - guard let superview = self.from.view?.superview else { - fatalError("Cannot Install Constraint. No superview. (\(self.sourceLocation.0), \(self.sourceLocation.1))") - } - installOnView = superview + NSLayoutConstraint.activate(layoutConstraints) + view.snp.add(layoutConstraints: layoutConstraints) } - guard self.installInfo?.view == nil || - self.installInfo?.view == installOnView else { - fatalError("Cannot Install Constraint. Already installed on different view. (\(self.sourceLocation.0), \(self.sourceLocation.1))") - } - - // setup array to store new layout constraints - var newLayoutConstraints = [LayoutConstraint]() - - // get attributes - let layoutFromAttributes = self.from.attributes.layoutAttributes - let layoutToAttributes = self.to.attributes.layoutAttributes - - // get layout from - let layoutFrom: ConstraintView = self.from.view! - - // get relation - let layoutRelation = self.relation.layoutRelation - - for layoutFromAttribute in layoutFromAttributes { - // get layout to attribute - let layoutToAttribute = (layoutToAttributes.count > 0) ? layoutToAttributes[0] : layoutFromAttribute - - // get layout constant - let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute) - - // get layout to - #if os(iOS) || os(tvOS) - var layoutTo: AnyObject? = self.to.view ?? self.to.layoutSupport - #else - var layoutTo: AnyObject? = self.to.view - #endif - if layoutTo == nil && layoutToAttribute != .width && layoutToAttribute != .height { - layoutTo = installOnView - } - - // create layout constraint - let layoutConstraint = LayoutConstraint( - item: layoutFrom, - attribute: layoutFromAttribute, - relatedBy: layoutRelation, - toItem: layoutTo, - attribute: layoutToAttribute, - multiplier: self.multiplier.constraintMultiplierTargetValue, - constant: layoutConstant - ) - - // set priority - layoutConstraint.priority = self.priority.constraintPriorityTargetValue - - // set constraint - layoutConstraint.constraint = self - - // append - newLayoutConstraints.append(layoutConstraint) - } - - // updating logic - if updateExisting { - - // get existing constraints for this view - let existingLayoutConstraints = layoutFrom.snp.installedLayoutConstraints.reversed() - - // array that will contain only new layout constraints to keep - var newLayoutConstraintsToKeep = [LayoutConstraint]() - - // begin looping - for layoutConstraint in newLayoutConstraints { - // layout constraint that should be updated - var updateLayoutConstraint: LayoutConstraint? = nil - - // loop through existing and check for match - for existingLayoutConstraint in existingLayoutConstraints { - if existingLayoutConstraint == layoutConstraint { - updateLayoutConstraint = existingLayoutConstraint - break - } - } - - // if we have existing one lets just update the constant - if updateLayoutConstraint != nil { - updateLayoutConstraint!.constant = layoutConstraint.constant - } - // otherwise add this layout constraint to new keep list - else { - newLayoutConstraintsToKeep.append(layoutConstraint) - } - } - - // set constraints to only new ones - newLayoutConstraints = newLayoutConstraintsToKeep - } - - // add constraints - #if SNAPKIT_DEPLOYMENT_LEGACY && (os(iOS) || os(tvOS)) - if #available(iOS 8.0, *) { - NSLayoutConstraint.activate(newLayoutConstraints) - } else { - installOnView?.addConstraints(newLayoutConstraints) - } - #else - NSLayoutConstraint.activate(newLayoutConstraints) - #endif - - // set install info - self.installInfo = ConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjects()) - - // store which layout constraints are installed for this constraint - for layoutConstraint in newLayoutConstraints { - self.installInfo!.layoutConstraints.add(layoutConstraint) - } - - // store the layout constraints against the layout from view - layoutFrom.snp.appendInstalledLayoutConstraints(newLayoutConstraints) - - return newLayoutConstraints - } - - internal func uninstallIfNeeded() { - defer { - self.installInfo = nil - } - - guard let installedLayoutConstraints = self.installInfo?.layoutConstraints.allObjects as? [LayoutConstraint], - installedLayoutConstraints.count > 0 else { - return - } - - #if SNAPKIT_DEPLOYMENT_LEGACY && !os(OSX) - if #available(iOS 8.0, *) { - NSLayoutConstraint.deactivate(installedLayoutConstraints) - } else if let installedOnView = installInfo?.view { - installedOnView.removeConstraints(installedLayoutConstraints) - } - #else - NSLayoutConstraint.deactivate(installedLayoutConstraints) - #endif - - // remove the constraints from the from item view - self.from.view?.snp.removeInstalledLayoutConstraints(installedLayoutConstraints) - } - - internal func activateIfNeeded() { - guard self.installInfo != nil else { - _ = self.installIfNeeded() - return - } - #if SNAPKIT_DEPLOYMENT_LEGACY - guard #available(iOS 8.0, OSX 10.10, *) else { - _ = self.installIfNeeded() - return - } - #endif - - guard let layoutConstraints = self.installInfo?.layoutConstraints.allObjects as? [LayoutConstraint], - layoutConstraints.count > 0 else { - return - } - - NSLayoutConstraint.activate(layoutConstraints) + print(view, layoutConstraints.count, existingLayoutConstraints.count) } internal func deactivateIfNeeded() { - #if SNAPKIT_DEPLOYMENT_LEGACY - guard #available(iOS 8.0, OSX 10.10, *) else { - return - } - #endif - - guard let layoutConstraints = self.installInfo?.layoutConstraints.allObjects as? [LayoutConstraint], - layoutConstraints.count > 0 else { - return - } - + let view = self.from.view! + let layoutConstraints = self.layoutConstraints.allObjects NSLayoutConstraint.deactivate(layoutConstraints) + view.snp.remove(layoutConstraints: layoutConstraints) + } +} + +extension Constraint: Hashable { + + public var hashValue: Int { + return self.layoutConstraints.hashValue } } -private final class ConstraintInstallInfo { - - private weak var view: ConstraintView? = nil - private let layoutConstraints: NSHashTable - - private init(view: ConstraintView?, layoutConstraints: NSHashTable) { - self.view = view - self.layoutConstraints = layoutConstraints - } - -} - -private func closestCommonSuperviewFromView(_ fromView: ConstraintView?, toView: ConstraintView?) -> ConstraintView? { - var views = Set() - var fromView = fromView - var toView = toView - repeat { - if let view = toView { - if views.contains(view) { - return view - } - views.insert(view) - toView = view.superview - } - if let view = fromView { - if views.contains(view) { - return view - } - views.insert(view) - fromView = view.superview - } - } while (fromView != nil || toView != nil) - - return nil -} - -private func ==(lhs: Constraint, rhs: Constraint) -> Bool { +public func ==(lhs: Constraint, rhs: Constraint) -> Bool { return (lhs.from == rhs.from && lhs.to == rhs.to && lhs.relation == rhs.relation && diff --git a/Source/ConstraintAttributes.swift b/Source/ConstraintAttributes.swift index 3c4cf68..7236d24 100644 --- a/Source/ConstraintAttributes.swift +++ b/Source/ConstraintAttributes.swift @@ -51,117 +51,120 @@ internal struct ConstraintAttributes: OptionSet { // normal - 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) } - internal static var CenterX: ConstraintAttributes { return self.init(256) } - internal static var CenterY: ConstraintAttributes { return self.init(512) } - internal static var Baseline: ConstraintAttributes { return self.init(1024) } + 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) } + internal static var centerX: ConstraintAttributes { return self.init(256) } + internal static var centerY: ConstraintAttributes { return self.init(512) } + internal static var lastBaseline: ConstraintAttributes { return self.init(1024) } + + @available(iOS 8.0, OSX 10.11, *) + internal static var firstBaseline: ConstraintAttributes { return self.init(2048) } @available(iOS 8.0, *) - internal static var FirstBaseline: ConstraintAttributes { return self.init(2048) } + internal static var leftMargin: ConstraintAttributes { return self.init(4096) } + @available(iOS 8.0, *) - internal static var LeftMargin: ConstraintAttributes { return self.init(4096) } + internal static var rightMargin: ConstraintAttributes { return self.init(8192) } + @available(iOS 8.0, *) - internal static var RightMargin: ConstraintAttributes { return self.init(8192) } + internal static var topMargin: ConstraintAttributes { return self.init(16384) } + @available(iOS 8.0, *) - internal static var TopMargin: ConstraintAttributes { return self.init(16384) } + internal static var bottomMargin: ConstraintAttributes { return self.init(32768) } + @available(iOS 8.0, *) - internal static var BottomMargin: ConstraintAttributes { return self.init(32768) } + internal static var leadingMargin: ConstraintAttributes { return self.init(65536) } + @available(iOS 8.0, *) - internal static var LeadingMargin: ConstraintAttributes { return self.init(65536) } + internal static var trailingMargin: ConstraintAttributes { return self.init(131072) } + @available(iOS 8.0, *) - internal static var TrailingMargin: ConstraintAttributes { return self.init(131072) } + internal static var centerXWithinMargins: ConstraintAttributes { return self.init(262144) } + @available(iOS 8.0, *) - internal static var CenterXWithinMargins: ConstraintAttributes { return self.init(262144) } - @available(iOS 8.0, *) - internal static var CenterYWithinMargins: ConstraintAttributes { return self.init(524288) } + internal static var centerYWithinMargins: ConstraintAttributes { return self.init(524288) } // aggregates - internal static var Edges: ConstraintAttributes { return self.init(15) } - internal static var Size: ConstraintAttributes { return self.init(192) } - internal static var Center: ConstraintAttributes { return self.init(768) } + internal static var edges: ConstraintAttributes { return self.init(15) } + internal static var size: ConstraintAttributes { return self.init(192) } + internal static var center: ConstraintAttributes { return self.init(768) } @available(iOS 8.0, *) - internal static var Margins: ConstraintAttributes { return self.init(61440) } + internal static var margins: ConstraintAttributes { return self.init(61440) } @available(iOS 8.0, *) - internal static var CenterWithinMargins: ConstraintAttributes { return self.init(786432) } + internal static var centerWithinMargins: ConstraintAttributes { return self.init(786432) } internal var layoutAttributes:[NSLayoutAttribute] { var attrs = [NSLayoutAttribute]() - if (self.contains(ConstraintAttributes.Left)) { + if (self.contains(ConstraintAttributes.left)) { attrs.append(.left) } - if (self.contains(ConstraintAttributes.Top)) { + if (self.contains(ConstraintAttributes.top)) { attrs.append(.top) } - if (self.contains(ConstraintAttributes.Right)) { + if (self.contains(ConstraintAttributes.right)) { attrs.append(.right) } - if (self.contains(ConstraintAttributes.Bottom)) { + if (self.contains(ConstraintAttributes.bottom)) { attrs.append(.bottom) } - if (self.contains(ConstraintAttributes.Leading)) { + if (self.contains(ConstraintAttributes.leading)) { attrs.append(.leading) } - if (self.contains(ConstraintAttributes.Trailing)) { + if (self.contains(ConstraintAttributes.trailing)) { attrs.append(.trailing) } - if (self.contains(ConstraintAttributes.Width)) { + if (self.contains(ConstraintAttributes.width)) { attrs.append(.width) } - if (self.contains(ConstraintAttributes.Height)) { + if (self.contains(ConstraintAttributes.height)) { attrs.append(.height) } - if (self.contains(ConstraintAttributes.CenterX)) { + if (self.contains(ConstraintAttributes.centerX)) { attrs.append(.centerX) } - if (self.contains(ConstraintAttributes.CenterY)) { + if (self.contains(ConstraintAttributes.centerY)) { attrs.append(.centerY) } - if (self.contains(ConstraintAttributes.Baseline)) { + if (self.contains(ConstraintAttributes.lastBaseline)) { attrs.append(.lastBaseline) } #if os(iOS) || os(tvOS) - #if SNAPKIT_DEPLOYMENT_LEGACY - guard #available(iOS 8.0, *) else { - return attrs - } - #endif - if (self.contains(ConstraintAttributes.FirstBaseline)) { + if (self.contains(ConstraintAttributes.firstBaseline)) { attrs.append(.firstBaseline) } - if (self.contains(ConstraintAttributes.LeftMargin)) { + if (self.contains(ConstraintAttributes.leftMargin)) { attrs.append(.leftMargin) } - if (self.contains(ConstraintAttributes.RightMargin)) { + if (self.contains(ConstraintAttributes.rightMargin)) { attrs.append(.rightMargin) } - if (self.contains(ConstraintAttributes.TopMargin)) { + if (self.contains(ConstraintAttributes.topMargin)) { attrs.append(.topMargin) } - if (self.contains(ConstraintAttributes.BottomMargin)) { + if (self.contains(ConstraintAttributes.bottomMargin)) { attrs.append(.bottomMargin) } - if (self.contains(ConstraintAttributes.LeadingMargin)) { + if (self.contains(ConstraintAttributes.leadingMargin)) { attrs.append(.leadingMargin) } - if (self.contains(ConstraintAttributes.TrailingMargin)) { + if (self.contains(ConstraintAttributes.trailingMargin)) { attrs.append(.trailingMargin) } - if (self.contains(ConstraintAttributes.CenterXWithinMargins)) { + if (self.contains(ConstraintAttributes.centerXWithinMargins)) { attrs.append(.centerXWithinMargins) } - if (self.contains(ConstraintAttributes.CenterYWithinMargins)) { + if (self.contains(ConstraintAttributes.centerYWithinMargins)) { attrs.append(.centerYWithinMargins) } #endif diff --git a/Source/ConstraintDescription.swift b/Source/ConstraintDescription.swift index d0189ae..6eae505 100644 --- a/Source/ConstraintDescription.swift +++ b/Source/ConstraintDescription.swift @@ -34,6 +34,7 @@ public class ConstraintDescription { internal var attributes: ConstraintAttributes internal var relation: ConstraintRelation? = nil internal var sourceLocation: (String, UInt)? = nil + internal var label: String? = nil internal var related: ConstraintItem? = nil internal var multiplier: ConstraintMultiplierTarget = 1.0 internal var constant: ConstraintConstantTarget = 0.0 @@ -51,6 +52,7 @@ public class ConstraintDescription { to: related, relation: relation, sourceLocation: sourceLocation, + label: self.label, multiplier: self.multiplier, constant: self.constant, priority: self.priority diff --git a/Source/ConstraintMaker.swift b/Source/ConstraintMaker.swift index 746b44b..94f1556 100644 --- a/Source/ConstraintMaker.swift +++ b/Source/ConstraintMaker.swift @@ -30,95 +30,109 @@ public class ConstraintMaker { public var left: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Left) + return self.makeExtendableWithAttributes(.left) } + public var top: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Top) + return self.makeExtendableWithAttributes(.top) } + public var bottom: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Bottom) + return self.makeExtendableWithAttributes(.bottom) } + public var right: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Right) + return self.makeExtendableWithAttributes(.right) } + public var leading: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Leading) + return self.makeExtendableWithAttributes(.leading) } + public var trailing: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Trailing) + return self.makeExtendableWithAttributes(.trailing) } + public var width: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Width) + return self.makeExtendableWithAttributes(.width) } + public var height: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Height) + return self.makeExtendableWithAttributes(.height) } public var centerX: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.CenterX) - } - public var centerY: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.CenterY) - } - public var baseline: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Baseline) + return self.makeExtendableWithAttributes(.centerX) } - @available(iOS 8.0, *) + public var centerY: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.centerY) + } + + @available(*, deprecated:0.40.0, message:"Use lastBaseline instead") + public var baseline: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.lastBaseline) + } + + public var lastBaseline: ConstraintMakerExtendable { + return self.makeExtendableWithAttributes(.lastBaseline) + } + + @available(iOS 8.0, OSX 10.11, *) public var firstBaseline: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.FirstBaseline) + return self.makeExtendableWithAttributes(.firstBaseline) } @available(iOS 8.0, *) public var leftMargin: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.LeftMargin) + return self.makeExtendableWithAttributes(.leftMargin) } @available(iOS 8.0, *) public var rightMargin: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.RightMargin) + return self.makeExtendableWithAttributes(.rightMargin) } @available(iOS 8.0, *) public var bottomMargin: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.BottomMargin) + return self.makeExtendableWithAttributes(.bottomMargin) } @available(iOS 8.0, *) public var leadingMargin: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.LeadingMargin) + return self.makeExtendableWithAttributes(.leadingMargin) } @available(iOS 8.0, *) public var trailingMargin: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.TrailingMargin) + return self.makeExtendableWithAttributes(.trailingMargin) } @available(iOS 8.0, *) public var centerXWithinMargins: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.CenterXWithinMargins) + return self.makeExtendableWithAttributes(.centerXWithinMargins) } @available(iOS 8.0, *) public var centerYWithinMargins: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.CenterYWithinMargins) + return self.makeExtendableWithAttributes(.centerYWithinMargins) } public var edges: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Edges) + return self.makeExtendableWithAttributes(.edges) } public var size: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Size) + return self.makeExtendableWithAttributes(.size) } @available(iOS 8.0, *) public var margins: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.Margins) + return self.makeExtendableWithAttributes(.margins) } @available(iOS 8.0, *) public var centerWithinMargins: ConstraintMakerExtendable { - return self.makeExtendableWithAttributes(ConstraintAttributes.CenterWithinMargins) + return self.makeExtendableWithAttributes(.centerWithinMargins) } private let view: ConstraintView @@ -153,7 +167,7 @@ public class ConstraintMaker { .filter { $0 != nil } .map { $0! } for constraint in constraints { - let _ = constraint.installIfNeeded() + constraint.activateIfNeeded(updatingExisting: false) } } @@ -170,13 +184,14 @@ public class ConstraintMaker { .filter { $0 != nil } .map { $0! } for constraint in constraints { - let _ = constraint.installIfNeeded(updateExisting: true) + constraint.activateIfNeeded(updatingExisting: true) } } internal static func removeConstraints(view: ConstraintView) { - for layoutConstraint in view.snp.installedLayoutConstraints { - layoutConstraint.constraint?.uninstall() + let constraints = view.snp.layoutConstraints.map { $0.constraint! } + for constraint in constraints { + constraint.deactivateIfNeeded() } } diff --git a/Source/ConstraintMakerExtendable.swift b/Source/ConstraintMakerExtendable.swift index 220bf16..2a57da9 100644 --- a/Source/ConstraintMakerExtendable.swift +++ b/Source/ConstraintMakerExtendable.swift @@ -31,126 +31,132 @@ public class ConstraintMakerExtendable: ConstraintMakerRelatable { public var left: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Left + self.description.attributes += .left return self } public var top: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Top + self.description.attributes += .top return self } public var bottom: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Bottom + self.description.attributes += .bottom return self } public var right: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Right + self.description.attributes += .right return self } public var leading: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Leading + self.description.attributes += .leading return self } public var trailing: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Trailing + self.description.attributes += .trailing return self } public var width: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Width + self.description.attributes += .width return self } public var height: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Height + self.description.attributes += .height return self } public var centerX: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.CenterX + self.description.attributes += .centerX return self } public var centerY: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.CenterY + self.description.attributes += .centerY return self } + @available(*, deprecated:0.40.0, message:"Use lastBaseline instead") public var baseline: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Baseline + self.description.attributes += .lastBaseline return self } - @available(iOS 8.0, *) + public var lastBaseline: ConstraintMakerExtendable { + self.description.attributes += .lastBaseline + return self + } + + @available(iOS 8.0, OSX 10.11, *) public var firstBaseline: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.FirstBaseline + self.description.attributes += .firstBaseline return self } @available(iOS 8.0, *) public var leftMargin: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.LeftMargin + self.description.attributes += .leftMargin return self } @available(iOS 8.0, *) public var rightMargin: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.RightMargin + self.description.attributes += .rightMargin return self } @available(iOS 8.0, *) public var bottomMargin: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.BottomMargin + self.description.attributes += .bottomMargin return self } @available(iOS 8.0, *) public var leadingMargin: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.LeadingMargin + self.description.attributes += .leadingMargin return self } @available(iOS 8.0, *) public var trailingMargin: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.TrailingMargin + self.description.attributes += .trailingMargin return self } @available(iOS 8.0, *) public var centerXWithinMargins: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.CenterXWithinMargins + self.description.attributes += .centerXWithinMargins return self } @available(iOS 8.0, *) public var centerYWithinMargins: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.CenterYWithinMargins + self.description.attributes += .centerYWithinMargins return self } public var edges: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Edges + self.description.attributes += .edges return self } public var size: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Size + self.description.attributes += .size return self } @available(iOS 8.0, *) public var margins: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.Margins + self.description.attributes += .margins return self } @available(iOS 8.0, *) public var centerWithinMargins: ConstraintMakerExtendable { - self.description.attributes += ConstraintAttributes.CenterWithinMargins + self.description.attributes += .centerWithinMargins return self } diff --git a/Source/ConstraintMakerFinalizable.swift b/Source/ConstraintMakerFinalizable.swift index 480f9c8..4e1379e 100644 --- a/Source/ConstraintMakerFinalizable.swift +++ b/Source/ConstraintMakerFinalizable.swift @@ -36,6 +36,12 @@ public class ConstraintMakerFinalizable { self.description = description } + @discardableResult + public func labeled(_ label: String) -> ConstraintMakerFinalizable { + self.description.label = label + return self + } + public var constraint: Constraint { return self.description.constraint! } diff --git a/Source/ConstraintMakerRelatable.swift b/Source/ConstraintMakerRelatable.swift index bab6369..c4141be 100644 --- a/Source/ConstraintMakerRelatable.swift +++ b/Source/ConstraintMakerRelatable.swift @@ -41,7 +41,7 @@ public class ConstraintMakerRelatable { let constant: ConstraintConstantTarget if let other = other as? ConstraintItem { - guard other.attributes == ConstraintAttributes.None || + guard other.attributes == ConstraintAttributes.none || other.attributes.layoutAttributes.count <= 1 || other.attributes.layoutAttributes == self.description.attributes.layoutAttributes else { fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))"); @@ -50,10 +50,10 @@ public class ConstraintMakerRelatable { related = other constant = 0.0 } else if let other = other as? ConstraintView { - related = ConstraintItem(target: other, attributes: ConstraintAttributes.None) + related = ConstraintItem(target: other, attributes: ConstraintAttributes.none) constant = 0.0 } else if let other = other as? ConstraintConstantTarget { - related = ConstraintItem(target: nil, attributes: ConstraintAttributes.None) + related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none) constant = other } else { fatalError("Invalid constraint. (\(file), \(line))") diff --git a/Source/ConstraintView+Extensions.swift b/Source/ConstraintView+Extensions.swift index 0e89a32..5406cdf 100644 --- a/Source/ConstraintView+Extensions.swift +++ b/Source/ConstraintView+Extensions.swift @@ -30,117 +30,116 @@ public extension ConstraintView { - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_left: ConstraintItem { return self.snp.left } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_top: ConstraintItem { return self.snp.top } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_right: ConstraintItem { return self.snp.right } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_bottom: ConstraintItem { return self.snp.bottom } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_leading: ConstraintItem { return self.snp.leading } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_trailing: ConstraintItem { return self.snp.trailing } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_width: ConstraintItem { return self.snp.width } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_height: ConstraintItem { return self.snp.height } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_centerX: ConstraintItem { return self.snp.centerX } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_centerY: ConstraintItem { return self.snp.centerY } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_baseline: ConstraintItem { return self.snp.baseline } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") - @available(iOS 8.0, OSX 10.11, *) + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, OSX 10.11, *) public var snp_firstBaseline: ConstraintItem { return self.snp.firstBaseline } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") - @available(iOS 8.0, OSX 10.11, *) + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") + @available(iOS 8.0, *) public var snp_leftMargin: ConstraintItem { return self.snp.leftMargin } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_topMargin: ConstraintItem { return self.snp.topMargin } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_rightMargin: ConstraintItem { return self.snp.rightMargin } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_bottomMargin: ConstraintItem { return self.snp.bottomMargin } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_trailingMargin: ConstraintItem { return self.snp.trailingMargin } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_centerYWithinMargins: ConstraintItem { return self.snp.centerYWithinMargins } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_edges: ConstraintItem { return self.snp.edges } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_size: ConstraintItem { return self.snp.size } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var snp_center: ConstraintItem { return self.snp.center } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_margins: ConstraintItem { return self.snp.margins } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") @available(iOS 8.0, *) public var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public func snp_prepareConstraints(_ closure: @noescape(make: ConstraintMaker) -> Void) -> [Constraint] { return self.snp.prepareConstraints(closure) } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public func snp_makeConstraints(_ closure: @noescape(make: ConstraintMaker) -> Void) { self.snp.makeConstraints(closure) } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public func snp_remakeConstraints(_ closure: @noescape(make: ConstraintMaker) -> Void) { self.snp.remakeConstraints(closure) } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public func snp_updateConstraints(_ closure: @noescape(make: ConstraintMaker) -> Void) { self.snp.updateConstraints(closure) } - @available(*, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.") public func snp_removeConstraints() { self.snp.removeConstraints() } diff --git a/Source/ConstraintViewController+Extensions.swift b/Source/ConstraintViewController+Extensions.swift index c7b18fe..4324b13 100644 --- a/Source/ConstraintViewController+Extensions.swift +++ b/Source/ConstraintViewController+Extensions.swift @@ -27,22 +27,22 @@ public extension ConstraintViewController { - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var topLayoutGuideTop: ConstraintItem { return self.snp.topLayoutGuideTop } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var topLayoutGuideBottom: ConstraintItem { return self.snp.topLayoutGuideBottom } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var bottomLayoutGuideTop: ConstraintItem { return self.snp.bottomLayoutGuideTop } - @available(iOS, deprecated:0.40.0, message:"Please use newer snp.* syntax.") + @available(iOS, deprecated:0.40.0, message:"Use newer snp.* syntax.") public var bottomLayoutGuideBottom: ConstraintItem { return self.snp.bottomLayoutGuideBottom } diff --git a/Source/ConstraintViewControllerDSL.swift b/Source/ConstraintViewControllerDSL.swift index b632c99..137b7b5 100644 --- a/Source/ConstraintViewControllerDSL.swift +++ b/Source/ConstraintViewControllerDSL.swift @@ -27,24 +27,24 @@ public struct ConstraintViewControllerDSL { - @available(iOS 7.0, *) + @available(iOS 8.0, *) public var topLayoutGuideTop: ConstraintItem { - return ConstraintItem(target: self.viewController.topLayoutGuide, attributes: ConstraintAttributes.Top) + return ConstraintItem(target: self.viewController.topLayoutGuide, attributes: ConstraintAttributes.top) } - @available(iOS 7.0, *) + @available(iOS 8.0, *) public var topLayoutGuideBottom: ConstraintItem { - return ConstraintItem(target: self.viewController.topLayoutGuide, attributes: ConstraintAttributes.Bottom) + return ConstraintItem(target: self.viewController.topLayoutGuide, attributes: ConstraintAttributes.bottom) } - @available(iOS 7.0, *) + @available(iOS 8.0, *) public var bottomLayoutGuideTop: ConstraintItem { - return ConstraintItem(target: self.viewController.bottomLayoutGuide, attributes: ConstraintAttributes.Top) + return ConstraintItem(target: self.viewController.bottomLayoutGuide, attributes: ConstraintAttributes.top) } - @available(iOS 7.0, *) + @available(iOS 8.0, *) public var bottomLayoutGuideBottom: ConstraintItem { - return ConstraintItem(target: self.viewController.bottomLayoutGuide, attributes: ConstraintAttributes.Bottom) + return ConstraintItem(target: self.viewController.bottomLayoutGuide, attributes: ConstraintAttributes.bottom) } internal let viewController: ConstraintViewController diff --git a/Source/ConstraintViewDSL.swift b/Source/ConstraintViewDSL.swift index 35a4c39..7d5f136 100644 --- a/Source/ConstraintViewDSL.swift +++ b/Source/ConstraintViewDSL.swift @@ -31,122 +31,123 @@ public struct ConstraintViewDSL { public var left: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Left) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.left) } public var top: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Top) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.top) } public var right: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Right) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.right) } public var bottom: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Bottom) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.bottom) } public var leading: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Leading) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.leading) } public var trailing: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Trailing) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.trailing) } public var width: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Width) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.width) } public var height: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Height) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.height) } public var centerX: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.CenterX) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.centerX) } public var centerY: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.CenterY) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.centerY) } - @available(*, deprecated:0.40.0, message:"Please use migrated .lastBaseline") + @available(*, deprecated:0.40.0, message:"Use .lastBaseline instead") public var baseline: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Baseline) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.lastBaseline) } @available(iOS 8.0, OSX 10.11, *) public var lastBaseline: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Baseline) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.lastBaseline) } @available(iOS 8.0, OSX 10.11, *) public var firstBaseline: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.FirstBaseline) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.firstBaseline) } @available(iOS 8.0, *) public var leftMargin: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.LeftMargin) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.leftMargin) } @available(iOS 8.0, *) public var topMargin: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.TopMargin) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.topMargin) } @available(iOS 8.0, *) public var rightMargin: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.RightMargin) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.rightMargin) } @available(iOS 8.0, *) public var bottomMargin: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.BottomMargin) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.bottomMargin) } @available(iOS 8.0, *) public var leadingMargin: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.LeadingMargin) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.leadingMargin) } @available(iOS 8.0, *) public var trailingMargin: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.TrailingMargin) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.trailingMargin) } @available(iOS 8.0, *) public var centerXWithinMargins: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.CenterXWithinMargins) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.centerXWithinMargins) } @available(iOS 8.0, *) public var centerYWithinMargins: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.CenterYWithinMargins) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.centerYWithinMargins) } public var edges: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Edges) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.edges) } public var size: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Size) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.size) } public var center: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Center) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.center) } @available(iOS 8.0, *) public var margins: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.Margins) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.margins) } @available(iOS 8.0, *) public var centerWithinMargins: ConstraintItem { - return ConstraintItem(target: self.view, attributes: ConstraintAttributes.CenterWithinMargins) + return ConstraintItem(target: self.view, attributes: ConstraintAttributes.centerWithinMargins) } + @discardableResult public func prepareConstraints(_ closure: @noescape (make: ConstraintMaker) -> Void) -> [Constraint] { return ConstraintMaker.prepareConstraints(view: self.view, closure: closure) } @@ -216,23 +217,23 @@ public struct ConstraintViewDSL { internal init(view: ConstraintView) { self.view = view + } - internal var installedLayoutConstraints: [LayoutConstraint] { - return objc_getAssociatedObject(self.view, &installedLayoutConstraintsKey) as? [LayoutConstraint] ?? [] + internal var layoutConstraints: [LayoutConstraint] { + return objc_getAssociatedObject(self.view, &layoutConstraintsKey) as? [LayoutConstraint] ?? [] } - internal func appendInstalledLayoutConstraints(_ layoutConstraints: [LayoutConstraint]) { - var newValue = self.installedLayoutConstraints - newValue += layoutConstraints - objc_setAssociatedObject(self.view, &installedLayoutConstraintsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + internal func add(layoutConstraints: [LayoutConstraint]) { + let merged = self.layoutConstraints + layoutConstraints + objc_setAssociatedObject(self.view, &layoutConstraintsKey, merged, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } - internal func removeInstalledLayoutConstraints(_ layoutConstraints: [LayoutConstraint]) { - let newValue = self.installedLayoutConstraints.filter { !layoutConstraints.contains($0) } - objc_setAssociatedObject(self.view, &installedLayoutConstraintsKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + internal func remove(layoutConstraints: [LayoutConstraint]) { + let merged = self.layoutConstraints.filter { !layoutConstraints.contains($0) } + objc_setAssociatedObject(self.view, &layoutConstraintsKey, merged, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } + } - private var labelKey: UInt8 = 0 -private var installedLayoutConstraintsKey: UInt8 = 0 +private var layoutConstraintsKey: UInt8 = 0 diff --git a/Source/LayoutConstraint.swift b/Source/LayoutConstraint.swift index 0bdf281..3dbe3ab 100644 --- a/Source/LayoutConstraint.swift +++ b/Source/LayoutConstraint.swift @@ -30,8 +30,16 @@ public class LayoutConstraint: NSLayoutConstraint { - internal var constraint: Constraint? = nil - public var label: String? = nil + public var label: String? { + get { + return self.identifier + } + set { + self.identifier = newValue + } + } + + internal var constraint: Constraint! = nil } diff --git a/Tests/Tests.swift b/Tests/Tests.swift index c5791d0..be74ad0 100644 --- a/Tests/Tests.swift +++ b/Tests/Tests.swift @@ -13,7 +13,7 @@ extension View { #endif import XCTest -import SnapKit +@testable import SnapKit class SnapKitTests: XCTestCase { @@ -29,4 +29,287 @@ class SnapKitTests: XCTestCase { super.tearDown() } + func testLayoutGuideConstraints() { + #if os(iOS) || os(tvOS) + let vc = UIViewController() + vc.view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300)) + + vc.view.addSubview(self.container) + + self.container.snp.makeConstraints { (make) -> Void in + make.top.equalTo(vc.snp.topLayoutGuideBottom) + make.bottom.equalTo(vc.snp.bottomLayoutGuideTop) + } + + XCTAssertEqual(vc.view.snp_constraints.count, 6, "Should have 6 constraints installed") + #endif + } + + func testMakeConstraints() { + let v1 = View() + let v2 = View() + 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.snp_constraints.count, 2, "Should have 2 constraints installed") + + v2.snp.makeConstraints { (make) -> Void in + make.edges.equalTo(v1) + return + } + + XCTAssertEqual(self.container.snp_constraints.count, 6, "Should have 6 constraints installed") + + } + + func testUpdateConstraints() { + let v1 = View() + let v2 = View() + self.container.addSubview(v1) + self.container.addSubview(v2) + + print(v1) + + 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.snp_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.snp_constraints.count, 2, "Should still have 2 constraints installed") + + } + + func testRemakeConstraints() { + let v1 = View() + let v2 = View() + 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.snp_constraints.count, 2, "Should have 2 constraints installed") + + v1.snp.remakeConstraints { (make) -> Void in + make.edges.equalTo(v2) + return + } + + XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed") + + } + + func testRemoveConstraints() { + let v1 = View() + let v2 = View() + 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.snp_constraints.count, 2, "Should have 2 constraints installed") + + v1.snp.removeConstraints() + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed") + + } + + func testPrepareConstraints() { + let v1 = View() + let v2 = View() + self.container.addSubview(v1) + self.container.addSubview(v2) + + let constraints = v1.snp.prepareConstraints { (make) -> Void in + make.edges.equalTo(v2) + return + } + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed") + + for constraint in constraints { + constraint.activate() + } + + XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed") + + for constraint in constraints { + constraint.deactivate() + } + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed") + + } + + func testReactivateConstraints() { + let v1 = View() + let v2 = View() + self.container.addSubview(v1) + self.container.addSubview(v2) + + let constraints = v1.snp.prepareConstraints { (make) -> Void in + make.edges.equalTo(v2) + return + } + + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed") + + for constraint in constraints { + constraint.activate() + } + + XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed") + + for constraint in constraints { + constraint.deactivate() + } + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed") + } + + func testActivateDeactivateConstraints() { + let v1 = View() + let v2 = View() + self.container.addSubview(v1) + self.container.addSubview(v2) + + var c1: Constraint? = nil + var c2: Constraint? = nil + + v1.snp.prepareConstraints { (make) -> Void in + c1 = make.top.equalTo(v2.snp.top).offset(50).constraint + c2 = make.left.equalTo(v2.snp.top).offset(50).constraint + return + } + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints") + + c1?.activate() + c2?.activate() + + XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints") + + c1?.deactivate() + c2?.deactivate() + + XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints") + + c1?.activate() + c2?.activate() + + XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints") + + } + + func testSizeConstraints() { + let view = View() + self.container.addSubview(view) + + view.snp.makeConstraints { (make) -> Void in + make.size.equalTo(CGSize(width: 50, height: 50)) + make.left.top.equalTo(self.container) + } + + XCTAssertEqual(view.snp_constraints.count, 2, "Should have 2 constraints") + + XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints") + + + let constraints = view.snp_constraints as! [NSLayoutConstraint] + + XCTAssertEqual(constraints[0].firstAttribute.rawValue, NSLayoutAttribute.width.rawValue, "Should be width") + XCTAssertEqual(constraints[1].firstAttribute.rawValue, NSLayoutAttribute.height.rawValue, "Should be height") + XCTAssertEqual(constraints[0].constant, 50, "Should be 50") + XCTAssertEqual(constraints[1].constant, 50, "Should be 50") + } + + func testConstraintIdentifier() { + let identifier = "Test-Identifier" + let view = View() + self.container.addSubview(view) + + view.snp.makeConstraints { (make) -> Void in + make.top.equalTo(self.container.snp.top).labeled(identifier) + } + + let constraints = container.snp_constraints as! [NSLayoutConstraint] + XCTAssertEqual(constraints[0].identifier, identifier, "Identifier should be 'Test'") + } +// +//// func testSuperviewConstraints() { +//// let view = View() +//// +//// container.addSubview(view) +//// +//// view.snp.makeConstraints { (make) -> Void in +//// make.top.equalToSuperview().inset(10) +//// make.bottom.equalToSuperview().inset(10) +//// } +//// +//// XCTAssertEqual(container.snp_constraints.count, 2, "Should have 2 constraints") +//// +//// let constraints = container.snp_constraints as! [NSLayoutConstraint] +//// +//// XCTAssertEqual(constraints[0].firstAttribute, NSLayoutAttribute.top, "Should be top") +//// XCTAssertEqual(constraints[1].firstAttribute, NSLayoutAttribute.bottom, "Should be bottom") +//// +//// XCTAssertEqual(constraints[0].secondAttribute, NSLayoutAttribute.top, "Should be top") +//// XCTAssertEqual(constraints[1].secondAttribute, NSLayoutAttribute.bottom, "Should be bottom") +//// +//// XCTAssertEqual(constraints[0].firstItem as? View, view, "Should be added subview") +//// XCTAssertEqual(constraints[1].firstItem as? View, view, "Should be added subview") +//// +//// XCTAssertEqual(constraints[0].secondItem as? View, container, "Should be containerView") +//// XCTAssertEqual(constraints[1].secondItem as? View, container, "Should be containerView") +//// +//// XCTAssertEqual(constraints[0].constant, 10, "Should be 10") +//// XCTAssertEqual(constraints[1].constant, -10, "Should be 10") +//// } +// +//// func testNativeConstraints() { +//// let view = View() +//// +//// container.addSubview(view) +//// +//// var topNativeConstraints: [LayoutConstraint]! +//// var topNativeConstraint: LayoutConstraint? +//// var sizeNativeConstraints: [LayoutConstraint]! +//// view.snp_makeConstraints { (make) -> Void in +//// let topConstraint = make.top.equalToSuperview().inset(10).constraint +//// topNativeConstraints = topConstraint.layoutConstraints +//// topNativeConstraint = topConstraint.layoutConstraints.first +//// let sizeConstraints = make.size.equalTo(50).constraint +//// sizeNativeConstraints = sizeConstraints.layoutConstraints +//// } +//// +//// XCTAssertEqual(topNativeConstraints.count, 1, "make.top should creates one native constraint") +//// XCTAssertEqual(topNativeConstraint?.constant, 10, "topNativeConstraint.constant is set to 10") +//// XCTAssertEqual(sizeNativeConstraints.count, 2, "make.tosize should create two native constraint") +//// XCTAssertEqual(sizeNativeConstraints[0].constant, 50, "sizeNativeConstraints should set size[0] to 50") +//// XCTAssertEqual(sizeNativeConstraints[1].constant, 50, "sizeNativeConstraints should set size[1] to 50") +//// } + }