From 2b00e7b50ccd272884a51e6b0b97ca3b378266f7 Mon Sep 17 00:00:00 2001 From: Robert Payne Date: Sun, 12 Apr 2015 23:32:03 +1200 Subject: [PATCH] Refactor Constraint -> ConcreteConstraint & Add Updaters! --- Source/Constraint.swift | 149 ++++++++++++++++++++++++----- Source/ConstraintDescription.swift | 18 ++-- Source/ConstraintMaker.swift | 10 +- 3 files changed, 141 insertions(+), 36 deletions(-) diff --git a/Source/Constraint.swift b/Source/Constraint.swift index 3cd820c..e3aefd4 100644 --- a/Source/Constraint.swift +++ b/Source/Constraint.swift @@ -27,17 +27,114 @@ import UIKit import AppKit #endif -public class Constraint { +/** + Used to expose API's for a Constraint +*/ +public protocol Constraint: class { - public func install() -> [LayoutConstraint] { + func install() -> [LayoutConstraint] + func uninstall() + func activate() + func deactivate() + + func updateOffset(amount: Float) -> Void + func updateOffset(amount: Double) -> Void + func updateOffset(amount: CGFloat) -> Void + func updateOffset(amount: Int) -> Void + func updateOffset(amount: UInt) -> Void + func updateOffset(amount: CGPoint) -> Void + func updateOffset(amount: CGSize) -> Void + func updateOffset(amount: EdgeInsets) -> Void + + func updateInsets(amount: EdgeInsets) -> Void + + func updatePriority(priority: Float) -> Void + func updatePriority(priority: Double) -> Void + func updatePriority(priority: CGFloat) -> Void + func updatePriority(priority: UInt) -> Void + func updatePriority(priority: Int) -> Void + func updatePriorityRequired() -> Void + func updatePriorityHigh() -> Void + func updatePriorityMedium() -> Void + func updatePriorityLow() -> Void + +} + +/** + Used internally to implement a ConcreteConstraint +*/ +internal class ConcreteConstraint: Constraint { + + internal func updateOffset(amount: Float) -> Void { + self.constant = amount + } + internal func updateOffset(amount: Double) -> Void { + self.updateOffset(Float(amount)) + } + internal func updateOffset(amount: CGFloat) -> Void { + self.updateOffset(Float(amount)) + } + internal func updateOffset(amount: Int) -> Void { + self.updateOffset(Float(amount)) + } + internal func updateOffset(amount: UInt) -> Void { + self.updateOffset(Float(amount)) + } + internal func updateOffset(amount: CGPoint) -> Void { + self.constant = amount + } + internal func updateOffset(amount: CGSize) -> Void { + self.constant = amount + } + internal func updateOffset(amount: EdgeInsets) -> Void { + self.constant = amount + } + + internal func updateInsets(amount: EdgeInsets) -> Void { + self.constant = EdgeInsets(top: amount.top, left: amount.left, bottom: -amount.bottom, right: -amount.right) + } + + internal func updatePriority(priority: Float) -> Void { + self.priority = priority + } + internal func updatePriority(priority: Double) -> Void { + self.updatePriority(Float(priority)) + } + internal func updatePriority(priority: CGFloat) -> Void { + self.updatePriority(Float(priority)) + } + internal func updatePriority(priority: UInt) -> Void { + self.updatePriority(Float(priority)) + } + internal func updatePriority(priority: Int) -> Void { + self.updatePriority(Float(priority)) + } + internal func updatePriorityRequired() -> Void { + self.updatePriority(Float(1000.0)) + } + internal func updatePriorityHigh() -> Void { + self.updatePriority(Float(750.0)) + } + internal func updatePriorityMedium() -> Void { + #if os(iOS) + self.updatePriority(Float(500.0)) + #else + self.updatePriority(Float(501.0)) + #endif + } + internal func updatePriorityLow() -> Void { + self.updatePriority(Float(250.0)) + } + + internal func install() -> [LayoutConstraint] { return self.installOnView(updateExisting: false) } - public func uninstall() { + internal func uninstall() { self.uninstallFromView() } - public func activate() { + internal func activate() { if NSLayoutConstraint.respondsToSelector("activateConstraints:") && self.installInfo != nil { let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint] if layoutConstraints.count > 0 { @@ -48,7 +145,7 @@ public class Constraint { } } - public func deactivate() { + internal func deactivate() { if NSLayoutConstraint.respondsToSelector("deactivateConstraints:") && self.installInfo != nil { let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint] if layoutConstraints.count > 0 { @@ -62,11 +159,28 @@ public class Constraint { private let fromItem: ConstraintItem private let toItem: ConstraintItem private let relation: ConstraintRelation - private var constant: Any - private var multiplier: Float - private var priority: Float + private let multiplier: Float + private var constant: Any { + didSet { + if let installInfo = self.installInfo { + for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] { + let attribute = (layoutConstraint.secondAttribute == .NotAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute + layoutConstraint.constant = attribute.snp_constantForValue(self.constant) + } + } + } + } + private var priority: Float { + didSet { + if let installInfo = self.installInfo { + for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] { + layoutConstraint.priority = self.priority + } + } + } + } - private var installInfo: ConstraintInstallInfo? = nil + private var installInfo: ConcreteConstraintInstallInfo? = nil internal init(fromItem: ConstraintItem, toItem: ConstraintItem, relation: ConstraintRelation, constant: Any, multiplier: Float, priority: Float) { self.fromItem = fromItem @@ -188,7 +302,7 @@ public class Constraint { installOnView!.addConstraints(newLayoutConstraints) // set install info - self.installInfo = ConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjectsHashTable()) + self.installInfo = ConcreteConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjectsHashTable()) // store which layout constraints are installed for this constraint for layoutConstraint in newLayoutConstraints { @@ -227,7 +341,7 @@ public class Constraint { } -private struct ConstraintInstallInfo { +private struct ConcreteConstraintInstallInfo { weak var view: View? = nil let layoutConstraints: NSHashTable @@ -342,19 +456,10 @@ private func closestCommonSuperviewBetween(fromView: View?, toView: View?) -> Vi return nil } -private func ==(left: Constraint, right: Constraint) -> Bool { +private func ==(left: ConcreteConstraint, right: ConcreteConstraint) -> Bool { return (left.fromItem == right.fromItem && left.toItem == right.toItem && left.relation == right.relation && left.multiplier == right.multiplier && left.priority == right.priority) -} - -//public protocol Constraint: class { -// -// func install() -> [LayoutConstraint] -// func uninstall() -> Void -// func activate() -> Void -// func deactivate() -> Void -// -//} +} \ No newline at end of file diff --git a/Source/ConstraintDescription.swift b/Source/ConstraintDescription.swift index 1b07790..8a51dc9 100644 --- a/Source/ConstraintDescription.swift +++ b/Source/ConstraintDescription.swift @@ -429,11 +429,11 @@ final internal class ConstraintDescription: ConstraintDescriptionExtendable, Con // MARK: Constraint internal var constraint: Constraint { - if self.createdConstraint == nil { + if self.concreteConstraint == nil { if self.relation == nil { fatalError("Attempting to create a constraint from a ConstraintDescription before it has been fully chained.") } - self.createdConstraint = Constraint( + self.concreteConstraint = ConcreteConstraint( fromItem: self.fromItem, toItem: self.toItem, relation: self.relation!, @@ -441,7 +441,7 @@ final internal class ConstraintDescription: ConstraintDescriptionExtendable, Con multiplier: self.multiplier, priority: self.priority) } - return self.createdConstraint! + return self.concreteConstraint! } // MARK: Private @@ -449,40 +449,40 @@ final internal class ConstraintDescription: ConstraintDescriptionExtendable, Con private let fromItem: ConstraintItem private var toItem: ConstraintItem { willSet { - if self.createdConstraint != nil { + if self.concreteConstraint != nil { fatalError("Attempting to modify a ConstraintDescription after it’s constraint has been created.") } } } private var relation: ConstraintRelation? { willSet { - if self.createdConstraint != nil { + if self.concreteConstraint != nil { fatalError("Attempting to modify a ConstraintDescription after it’s constraint has been created.") } } } private var constant: Any = Float(0.0) { willSet { - if self.createdConstraint != nil { + if self.concreteConstraint != nil { fatalError("Attempting to modify a ConstraintDescription after it’s constraint has been created.") } } } private var multiplier: Float = 1.0 { willSet { - if self.createdConstraint != nil { + if self.concreteConstraint != nil { fatalError("Attempting to modify a ConstraintDescription after it’s constraint has been created.") } } } private var priority: Float = 1000.0 { willSet { - if self.createdConstraint != nil { + if self.concreteConstraint != nil { fatalError("Attempting to modify a ConstraintDescription after it’s constraint has been created.") } } } - private var createdConstraint: Constraint? = nil + private var concreteConstraint: ConcreteConstraint? = nil private func addConstraint(attributes: ConstraintAttributes) -> ConstraintDescription { if self.relation == nil { diff --git a/Source/ConstraintMaker.swift b/Source/ConstraintMaker.swift index 12ac44b..bc19cd1 100644 --- a/Source/ConstraintMaker.swift +++ b/Source/ConstraintMaker.swift @@ -118,7 +118,7 @@ final public class ConstraintMaker { self.view = view } - internal weak var view: View? + internal let view: View internal var constraintDescriptions = [ConstraintDescription]() internal func makeConstraintDescription(attributes: ConstraintAttributes) -> ConstraintDescription { @@ -144,7 +144,7 @@ final public class ConstraintMaker { let maker = ConstraintMaker(view: view) closure(make: maker) - let constraints = maker.constraintDescriptions.map { $0.constraint } + let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint } for constraint in constraints { constraint.installOnView(updateExisting: false) } @@ -160,7 +160,7 @@ final public class ConstraintMaker { closure(make: maker) self.removeConstraints(view) - let constraints = maker.constraintDescriptions.map { $0.constraint } + let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint } for constraint in constraints { constraint.installOnView(updateExisting: false) } @@ -175,7 +175,7 @@ final public class ConstraintMaker { let maker = ConstraintMaker(view: view) closure(make: maker) - let constraints = maker.constraintDescriptions.map { $0.constraint } + let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint} for constraint in constraints { constraint.installOnView(updateExisting: true) } @@ -183,7 +183,7 @@ final public class ConstraintMaker { internal class func removeConstraints(view: View) { for existingLayoutConstraint in view.snp_installedLayoutConstraints { - existingLayoutConstraint.snp_constraint?.uninstallFromView() + existingLayoutConstraint.snp_constraint?.uninstall() } } } \ No newline at end of file