Преглед изворни кода

Merge branch 'feature/0.40.0' of github.com:SnapKit/SnapKit into develop

# Conflicts:
#	.travis.yml
#	CHANGELOG.md
#	README.md
#	SnapKit.podspec
#	SnapKit.xcodeproj/project.pbxproj
#	SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit OSX.xcscheme
#	SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit iOS.xcscheme
#	Source/Constraint.swift
#	Source/ConstraintAttributes.swift
#	Source/ConstraintDescription.swift
#	Source/ConstraintMaker.swift
#	Source/ConstraintView.swift
#	Source/Debugging.swift
#	Source/LayoutConstraint.swift
#	Source/View+SnapKit.swift
#	Tests/Tests.swift
Robert Payne пре 9 година
родитељ
комит
f03dd0e85f
42 измењених фајлова са 2780 додато и 2594 уклоњено
  1. 7 12
      .travis.yml
  2. 26 0
      CHANGELOG.md
  3. 1 2
      README.md
  4. 2 2
      SnapKit.podspec
  5. 193 595
      SnapKit.xcodeproj/project.pbxproj
  6. 0 113
      SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit OSX.xcscheme
  7. 56 0
      SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit Tests.xcscheme
  8. 0 113
      SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit tvOS.xcscheme
  9. 9 9
      SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit.xcscheme
  10. 170 437
      Source/Constraint.swift
  11. 102 98
      Source/ConstraintAttributes.swift
  12. 9 14
      Source/ConstraintConfig.swift
  13. 147 0
      Source/ConstraintConstantTarget.swift
  14. 179 0
      Source/ConstraintDSL.swift
  15. 35 596
      Source/ConstraintDescription.swift
  16. 72 0
      Source/ConstraintInsetTarget.swift
  17. 35 0
      Source/ConstraintInsets.swift
  18. 24 31
      Source/ConstraintItem.swift
  19. 36 0
      Source/ConstraintLayoutGuide.swift
  20. 45 0
      Source/ConstraintLayoutGuideDSL.swift
  21. 36 0
      Source/ConstraintLayoutSupport.swift
  22. 26 15
      Source/ConstraintLayoutSupportDSL.swift
  23. 123 113
      Source/ConstraintMaker.swift
  24. 56 0
      Source/ConstraintMakerEditable.swift
  25. 163 0
      Source/ConstraintMakerExtendable.swift
  26. 49 0
      Source/ConstraintMakerFinalizable.swift
  27. 67 0
      Source/ConstraintMakerPriortizable.swift
  28. 95 0
      Source/ConstraintMakerRelatable.swift
  29. 75 0
      Source/ConstraintMultiplierTarget.swift
  30. 69 0
      Source/ConstraintOffsetTarget.swift
  31. 75 0
      Source/ConstraintPriorityTarget.swift
  32. 37 13
      Source/ConstraintRelatableTarget.swift
  33. 14 14
      Source/ConstraintRelation.swift
  34. 152 0
      Source/ConstraintView+Extensions.swift
  35. 35 0
      Source/ConstraintView.swift
  36. 135 0
      Source/ConstraintViewDSL.swift
  37. 78 117
      Source/Debugging.swift
  38. 22 28
      Source/LayoutConstraint.swift
  39. 36 0
      Source/UILayoutGuide+Extensions.swift
  40. 36 0
      Source/UILayoutSupport+Extensions.swift
  41. 0 183
      Source/View+SnapKit.swift
  42. 253 89
      Tests/Tests.swift

+ 7 - 12
.travis.yml

@@ -1,15 +1,10 @@
 language: objective-c
-osx_image: xcode7.3
-branches:
-  only:
-    - master
-    - develop
+osx_image: xcode8
+
 env:
-  - LC_CTYPE=en_US.UTF-8 LANG=en_US.UTF-8
-before_install:
-  - gem install xcpretty -N
+  - ACTION=test  PLATFORM=Mac     DESTINATION='platform=OS X'
+  - ACTION=test  PLATFORM=iOS     DESTINATION='platform=iOS Simulator,name=iPhone 6S'
+  - ACTION=test  PLATFORM=tvOS    DESTINATION='platform=tvOS Simulator,name=Apple TV 1080p'
+
 script:
-  - set -o pipefail
-  - xcodebuild -project SnapKit.xcodeproj -scheme "SnapKit iOS" -sdk iphonesimulator -destination "platform=iOS Simulator,name=iPhone 6" ONLY_ACTIVE_ARCH=NO  test | xcpretty -c
-  - xcodebuild -project SnapKit.xcodeproj -scheme "SnapKit OSX" ONLY_ACTIVE_ARCH=YES test | xcpretty -c
-  - pod lib lint --quick
+  - set -o pipefail && xcodebuild -scheme SnapKit -destination "$DESTINATION" $ACTION | xcpretty

+ 26 - 0
CHANGELOG.md

@@ -1,6 +1,32 @@
 CHANGELOG
 =======
 
+# 0.40.0.beta - WIP
+
+**SnapKit 0.40.0** is a complete re-write to take advantage of modern Swift 3.0 as well as
+clean up the API. As such please use with caution and check your apps thoroughly
+
+### Breaking
+
+* iOS 7.0 support has been removed
+* `install` and `uninstall` have been removed, use `activate` and `deactivate` instead
+* DSL is now accessed through `.snp.*` rather than `.snp_*`. For example `view.snp.makeConstraints { }`
+* Constraints are now updated through `update(offset:)`, `update(inset:)` and `update(priority:)`
+* `.inset()` will no longer take `CGPoint` or `CGSize` as input
+* `.offset()` will no longer take `CGPoint`, `CGSize`, `EdgeInsets` as input
+* `updateConstraints` will no longer allow creating new constraints unless there are no existing constraints for the view. If it does generate new constraints it will throw a fatal error.
+* `UIEdgeInsets` are now have their right and bottom value inverted for more natural results such as `make.edges.equalTo(UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)).inset()`
+
+### Enhancements
+
+* Debugging output has been improved to show exact file/line number from which the broken constraint was created
+* Exceptions thrown during constraint creation have been replaced with `fatalError` with better output
+* Constraints are now installed through `NSLayoutConstraint.activate` and what view they are added to is now deferred to UIKit
+* Added `var contentHugging<Axis>Priority: CGFloat` to `make`
+* Added `var contentCompressionResistance<Axis>Priority: CGFloat` to `make`
+* Added support for `UILayoutGuide` via `make.left.equalTo(guide.snp.top)`
+* Added support for constraining edges to margins or vice versa via `make.edges.equalTo(other.snp.margins)`
+
 # 0.22.0 - August 8 2016
 
 * Added `layoutConstraint` getter to `Constraint` to get the underlying NSLayoutConstraints created by a constraint

+ 1 - 2
README.md

@@ -17,7 +17,7 @@ class MyViewController: UIViewController {
         super.viewDidLoad()
 
         self.view.addSubview(box)
-        box.snp_makeConstraints { make in
+        box.snp.makeConstraints { (make) -> Void in
            make.width.height.equalTo(50)
            make.center.equalTo(self.view)
         }
@@ -30,7 +30,6 @@ class MyViewController: UIViewController {
 
 * [Documentation](http://snapkit.io/docs/)
 * [F.A.Q.](http://snapkit.io/faq/)
-* [Legacy Platforms (iOS 7.0, OS X 10.9)](http://snapkit.io/legacy-platforms/)
 
 ## License
 

+ 2 - 2
SnapKit.podspec

@@ -1,12 +1,12 @@
 Pod::Spec.new do |s|
   s.name = 'SnapKit'
-  s.version = '0.22.0'
+  s.version = '0.40.0.beta4'
   s.license = 'MIT'
   s.summary = 'Harness the power of auto layout with a simplified, chainable, and compile time safe syntax.'
   s.homepage = 'https://github.com/SnapKit/SnapKit'
   s.authors = { 'Robert Payne' => 'robertpayne@me.com' }
   s.social_media_url = 'http://twitter.com/robertjpayne'
-  s.source = { :git => 'https://github.com/SnapKit/SnapKit.git', :tag => '0.22.0' }
+  s.source = { :git => 'https://github.com/SnapKit/SnapKit.git', :tag => '0.40.0.beta4' }
 
   s.ios.deployment_target = '8.0'
   s.osx.deployment_target = '10.10'

Разлика између датотеке није приказан због своје велике величине
+ 193 - 595
SnapKit.xcodeproj/project.pbxproj


+ 0 - 113
SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit OSX.xcscheme

@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "0800"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
-               BuildableName = "SnapKit.framework"
-               BlueprintName = "SnapKit OSX"
-               ReferencedContainer = "container:SnapKit.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "NO"
-            buildForProfiling = "NO"
-            buildForArchiving = "NO"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "EECDB3831AC0C9D4006BBC11"
-               BuildableName = "SnapKit OSX Tests.xctest"
-               BlueprintName = "SnapKit OSX Tests"
-               ReferencedContainer = "container:SnapKit.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "EECDB3831AC0C9D4006BBC11"
-               BuildableName = "SnapKit OSX Tests.xctest"
-               BlueprintName = "SnapKit OSX Tests"
-               ReferencedContainer = "container:SnapKit.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-      </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
-            BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit OSX"
-            ReferencedContainer = "container:SnapKit.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
-            BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit OSX"
-            ReferencedContainer = "container:SnapKit.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "EECDB3791AC0C9D4006BBC11"
-            BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit OSX"
-            ReferencedContainer = "container:SnapKit.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>

+ 56 - 0
SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit Tests.xcscheme

@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "0800"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "EEBCC9E119CC627D0083B827"
+               BuildableName = "SnapKit Tests.xctest"
+               BlueprintName = "SnapKit Tests"
+               ReferencedContainer = "container:SnapKit.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <AdditionalOptions>
+      </AdditionalOptions>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 0 - 113
SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit tvOS.xcscheme

@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Scheme
-   LastUpgradeVersion = "0800"
-   version = "1.3">
-   <BuildAction
-      parallelizeBuildables = "YES"
-      buildImplicitDependencies = "YES">
-      <BuildActionEntries>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "YES"
-            buildForProfiling = "YES"
-            buildForArchiving = "YES"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "537DCE911C35CC8800B5B899"
-               BuildableName = "SnapKit.framework"
-               BlueprintName = "SnapKit tvOS"
-               ReferencedContainer = "container:SnapKit.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-         <BuildActionEntry
-            buildForTesting = "YES"
-            buildForRunning = "NO"
-            buildForProfiling = "NO"
-            buildForArchiving = "NO"
-            buildForAnalyzing = "YES">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "537DCEAE1C35D90A00B5B899"
-               BuildableName = "SnapKit tvOS Tests.xctest"
-               BlueprintName = "SnapKit tvOS Tests"
-               ReferencedContainer = "container:SnapKit.xcodeproj">
-            </BuildableReference>
-         </BuildActionEntry>
-      </BuildActionEntries>
-   </BuildAction>
-   <TestAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES">
-      <Testables>
-         <TestableReference
-            skipped = "NO">
-            <BuildableReference
-               BuildableIdentifier = "primary"
-               BlueprintIdentifier = "537DCEAE1C35D90A00B5B899"
-               BuildableName = "SnapKit tvOS Tests.xctest"
-               BlueprintName = "SnapKit tvOS Tests"
-               ReferencedContainer = "container:SnapKit.xcodeproj">
-            </BuildableReference>
-         </TestableReference>
-      </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "537DCE911C35CC8800B5B899"
-            BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit tvOS"
-            ReferencedContainer = "container:SnapKit.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </TestAction>
-   <LaunchAction
-      buildConfiguration = "Debug"
-      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
-      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      launchStyle = "0"
-      useCustomWorkingDirectory = "NO"
-      ignoresPersistentStateOnLaunch = "NO"
-      debugDocumentVersioning = "YES"
-      debugServiceExtension = "internal"
-      allowLocationSimulation = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "537DCE911C35CC8800B5B899"
-            BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit tvOS"
-            ReferencedContainer = "container:SnapKit.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
-   </LaunchAction>
-   <ProfileAction
-      buildConfiguration = "Release"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      savedToolIdentifier = ""
-      useCustomWorkingDirectory = "NO"
-      debugDocumentVersioning = "YES">
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "537DCE911C35CC8800B5B899"
-            BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit tvOS"
-            ReferencedContainer = "container:SnapKit.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-   </ProfileAction>
-   <AnalyzeAction
-      buildConfiguration = "Debug">
-   </AnalyzeAction>
-   <ArchiveAction
-      buildConfiguration = "Release"
-      revealArchiveInOrganizer = "YES">
-   </ArchiveAction>
-</Scheme>

+ 9 - 9
SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit iOS.xcscheme → SnapKit.xcodeproj/xcshareddata/xcschemes/SnapKit.xcscheme

@@ -16,7 +16,7 @@
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
                BuildableName = "SnapKit.framework"
-               BlueprintName = "SnapKit iOS"
+               BlueprintName = "SnapKit"
                ReferencedContainer = "container:SnapKit.xcodeproj">
             </BuildableReference>
          </BuildActionEntry>
@@ -28,9 +28,9 @@
             buildForAnalyzing = "YES">
             <BuildableReference
                BuildableIdentifier = "primary"
-               BlueprintIdentifier = "EEBCC9E119CC627D0083B827"
-               BuildableName = "SnapKit iOS Tests.xctest"
-               BlueprintName = "SnapKit iOS Tests"
+               BlueprintIdentifier = "537DCEAE1C35D90A00B5B899"
+               BuildableName = "SnapKit tvOS Tests.xctest"
+               BlueprintName = "SnapKit tvOS Tests"
                ReferencedContainer = "container:SnapKit.xcodeproj">
             </BuildableReference>
          </BuildActionEntry>
@@ -47,8 +47,8 @@
             <BuildableReference
                BuildableIdentifier = "primary"
                BlueprintIdentifier = "EEBCC9E119CC627D0083B827"
-               BuildableName = "SnapKit iOS Tests.xctest"
-               BlueprintName = "SnapKit iOS Tests"
+               BuildableName = "SnapKit Tests.xctest"
+               BlueprintName = "SnapKit Tests"
                ReferencedContainer = "container:SnapKit.xcodeproj">
             </BuildableReference>
          </TestableReference>
@@ -58,7 +58,7 @@
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
             BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit iOS"
+            BlueprintName = "SnapKit"
             ReferencedContainer = "container:SnapKit.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
@@ -80,7 +80,7 @@
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
             BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit iOS"
+            BlueprintName = "SnapKit"
             ReferencedContainer = "container:SnapKit.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
@@ -98,7 +98,7 @@
             BuildableIdentifier = "primary"
             BlueprintIdentifier = "EEBCC9D719CC627D0083B827"
             BuildableName = "SnapKit.framework"
-            BlueprintName = "SnapKit iOS"
+            BlueprintName = "SnapKit"
             ReferencedContainer = "container:SnapKit.xcodeproj">
          </BuildableReference>
       </MacroExpansion>

+ 170 - 437
Source/Constraint.swift

@@ -22,496 +22,229 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to expose API's for a Constraint
-*/
 public class Constraint {
     
-    public func install() -> [LayoutConstraint] { fatalError("Must be implemented by Concrete subclass.") }
-    public func uninstall() -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func activate() -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func deactivate() -> Void { fatalError("Must be implemented by Concrete subclass.") }
+    internal let sourceLocation: (String, UInt)
+    internal let label: String?
     
-    public func updateOffset(amount: Float) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: Double) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: CGFloat) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: Int) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: UInt) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: CGPoint) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: CGSize) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updateOffset(amount: EdgeInsets) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    
-    public func updateInsets(amount: EdgeInsets) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    
-    public func updatePriority(priority: Float) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriority(priority: Double) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriority(priority: CGFloat) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriority(priority: UInt) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriority(priority: Int) -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriorityRequired() -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") }
-    public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") }
-
-    public var layoutConstraints: [LayoutConstraint] { fatalError("Must be implemented by Concrete subclass.") }
-    
-    internal var makerFile: String = "Unknown"
-    internal var makerLine: UInt = 0
-    
-}
-
-/**
-    Used internally to implement a ConcreteConstraint
-*/
-internal class ConcreteConstraint: Constraint {
-    
-    internal override func updateOffset(amount: Float) -> Void {
-        self.constant = amount
-    }
-    internal override func updateOffset(amount: Double) -> Void {
-        self.updateOffset(Float(amount))
-    }
-    internal override func updateOffset(amount: CGFloat) -> Void {
-        self.updateOffset(Float(amount))
-    }
-    internal override func updateOffset(amount: Int) -> Void {
-        self.updateOffset(Float(amount))
-    }
-    internal override func updateOffset(amount: UInt) -> Void {
-        self.updateOffset(Float(amount))
-    }
-    internal override func updateOffset(amount: CGPoint) -> Void {
-        self.constant = amount
-    }
-    internal override func updateOffset(amount: CGSize) -> Void {
-        self.constant = amount
-    }
-    internal override func updateOffset(amount: EdgeInsets) -> Void {
-        self.constant = amount
-    }
-    
-    internal override func updateInsets(amount: EdgeInsets) -> Void {
-        self.constant = EdgeInsets(top: amount.top, left: amount.left, bottom: -amount.bottom, right: -amount.right)
-    }
-    
-    internal override func updatePriority(priority: Float) -> Void {
-        self.priority = priority
-    }
-    internal override func updatePriority(priority: Double) -> Void {
-        self.updatePriority(Float(priority))
-    }
-    internal override func updatePriority(priority: CGFloat) -> Void {
-        self.updatePriority(Float(priority))
-    }
-    internal override func updatePriority(priority: UInt) -> Void {
-        self.updatePriority(Float(priority))
-    }
-    internal override func updatePriority(priority: Int) -> Void {
-        self.updatePriority(Float(priority))
-    }
-    internal override func updatePriorityRequired() -> Void {
-        self.updatePriority(Float(1000.0))
-    }
-    internal override func updatePriorityHigh() -> Void {
-        self.updatePriority(Float(750.0))
-    }
-    internal override func updatePriorityMedium() -> Void {
-        #if os(iOS) || os(tvOS)
-        self.updatePriority(Float(500.0))
-        #else
-        self.updatePriority(Float(501.0))
-        #endif
-    }
-    internal override func updatePriorityLow() -> Void {
-        self.updatePriority(Float(250.0))
-    }
-    
-    internal override func install() -> [LayoutConstraint] {
-        return self.installOnView(updateExisting: false, file: self.makerFile, line: self.makerLine)
-    }
-    
-    internal override func uninstall() -> Void {
-        self.uninstallFromView()
-    }
-    
-    internal override func activate() -> Void {
-        guard self.installInfo != nil else {
-            self.install()
-            return
-        }
-        #if SNAPKIT_DEPLOYMENT_LEGACY
-        guard #available(iOS 8.0, OSX 10.10, *) else {
-            self.install()
-            return
-        }
-        #endif
-        let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint]
-        if layoutConstraints.count > 0 {
-            NSLayoutConstraint.activateConstraints(layoutConstraints)
-        }
-    }
-    
-    internal override func deactivate() -> Void {
-        guard self.installInfo != nil else {
-            return
-        }
-        #if SNAPKIT_DEPLOYMENT_LEGACY
-        guard #available(iOS 8.0, OSX 10.10, *) else {
-            return
-        }
-        #endif
-        let layoutConstraints = self.installInfo!.layoutConstraints.allObjects as! [LayoutConstraint]
-        if layoutConstraints.count > 0 {
-            NSLayoutConstraint.deactivateConstraints(layoutConstraints)
-        }
-    }
-    
-    private let fromItem: ConstraintItem
-    private let toItem: ConstraintItem
+    private let from: ConstraintItem
+    private let to: ConstraintItem
     private let relation: ConstraintRelation
-    private let multiplier: Float
-    private var constant: Any {
+    private let multiplier: ConstraintMultiplierTarget
+    private var constant: ConstraintConstantTarget {
         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)
-                }
-            }
+            self.updateConstantAndPriorityIfNeeded()
         }
     }
-    private var priority: Float {
+    private var priority: ConstraintPriorityTarget {
         didSet {
-            if let installInfo = self.installInfo {
-                for layoutConstraint in installInfo.layoutConstraints.allObjects as! [LayoutConstraint] {
-                    layoutConstraint.priority = self.priority
-                }
-            }
+          self.updateConstantAndPriorityIfNeeded()
         }
     }
+    private var layoutConstraints: [LayoutConstraint]
     
-    private let label: String?
+    // MARK: Initialization
     
-    private var installInfo: ConcreteConstraintInstallInfo? = nil
-    
-    override var layoutConstraints: [LayoutConstraint] {
-        if installInfo == nil {
-            install()
-        }
-        
-        guard let installInfo = installInfo else {
-            return []
-        }
-        return installInfo.layoutConstraints.allObjects as! [LayoutConstraint]
-    }
-
-    internal init(fromItem: ConstraintItem, toItem: ConstraintItem, relation: ConstraintRelation, constant: Any, multiplier: Float, priority: Float, label: String? = nil) {
-        self.fromItem = fromItem
-        self.toItem = toItem
+    internal init(from: ConstraintItem,
+                  to: ConstraintItem,
+                  relation: ConstraintRelation,
+                  sourceLocation: (String, UInt),
+                  label: String?,
+                  multiplier: ConstraintMultiplierTarget,
+                  constant: ConstraintConstantTarget,
+                  priority: ConstraintPriorityTarget) {
+        self.from = from
+        self.to = to
         self.relation = relation
-        self.constant = constant
+        self.sourceLocation = sourceLocation
+        self.label = label
         self.multiplier = multiplier
+        self.constant = constant
         self.priority = priority
-        self.label = label
-    }
-    
-    internal func installOnView(updateExisting updateExisting: Bool = false, file: String? = nil, line: UInt? = nil) -> [LayoutConstraint] {
-        var installOnView: View? = nil
-        if self.toItem.view != nil {
-            installOnView = closestCommonSuperviewFromView(self.fromItem.view, toView: self.toItem.view)
-            if installOnView == nil {
-                NSException(name: "Cannot Install Constraint", reason: "No common superview between views (@\(self.makerFile)#\(self.makerLine))", userInfo: nil).raise()
-                return []
-            }
-        } else {
-            
-            if self.fromItem.attributes.isSubsetOf(ConstraintAttributes.Width.union(.Height)) {
-                installOnView = self.fromItem.view
-            } else {
-                installOnView = self.fromItem.view?.superview
-                if installOnView == nil {
-                    NSException(name: "Cannot Install Constraint", reason: "Missing superview (@\(self.makerFile)#\(self.makerLine))", userInfo: nil).raise()
-                    return []
-                }
-            }
-        }
+        self.layoutConstraints = []
         
-        if let installedOnView = self.installInfo?.view {
-            if installedOnView != installOnView {
-                NSException(name: "Cannot Install Constraint", reason: "Already installed on different view. (@\(self.makerFile)#\(self.makerLine))", userInfo: nil).raise()
-                return []
-            }
-            return self.installInfo?.layoutConstraints.allObjects as? [LayoutConstraint] ?? []
-        }
-        
-        var newLayoutConstraints = [LayoutConstraint]()
-        let layoutFromAttributes = self.fromItem.attributes.layoutAttributes
-        let layoutToAttributes = self.toItem.attributes.layoutAttributes
+        // get attributes
+        let layoutFromAttributes = self.from.attributes.layoutAttributes
+        let layoutToAttributes = self.to.attributes.layoutAttributes
         
         // get layout from
-        let layoutFrom: View? = self.fromItem.view
+        let layoutFrom: ConstraintView = self.from.view!
         
-        // get layout relation
-        let layoutRelation: NSLayoutRelation = self.relation.layoutRelation
+        // get relation
+        let layoutRelation = self.relation.layoutRelation
         
         for layoutFromAttribute in layoutFromAttributes {
             // get layout to attribute
-            let layoutToAttribute = (layoutToAttributes.count > 0) ? layoutToAttributes[0] : layoutFromAttribute
+            let layoutToAttribute: NSLayoutAttribute
+            #if os(iOS) || os(tvOS)
+                if layoutToAttributes.count > 0 {
+                    if self.from.attributes == .edges && self.to.attributes == .margins {
+                        switch layoutFromAttribute {
+                        case .left:
+                            layoutToAttribute = .leftMargin
+                        case .right:
+                            layoutToAttribute = .rightMargin
+                        case .top:
+                            layoutToAttribute = .topMargin
+                        case .bottom:
+                            layoutToAttribute = .bottomMargin
+                        default:
+                            fatalError()
+                        }
+                    } else if self.from.attributes == .margins && self.to.attributes == .edges {
+                        switch layoutFromAttribute {
+                        case .leftMargin:
+                            layoutToAttribute = .left
+                        case .rightMargin:
+                            layoutToAttribute = .right
+                        case .topMargin:
+                            layoutToAttribute = .top
+                        case .bottomMargin:
+                            layoutToAttribute = .bottom
+                        default:
+                            fatalError()
+                        }
+                    } else if self.from.attributes == self.to.attributes {
+                        layoutToAttribute = layoutFromAttribute
+                    } else {
+                        layoutToAttribute = layoutToAttributes[0]
+                    }
+                } else {
+                    layoutToAttribute = layoutFromAttribute
+                }
+            #else
+                if layoutToAttributes.count > 0 {
+                    layoutToAttribute = layoutToAttributes[0]
+                } else {
+                    layoutToAttribute = layoutFromAttribute
+                }
+            #endif
             
             // get layout constant
-            let layoutConstant: CGFloat = layoutToAttribute.snp_constantForValue(self.constant)
+            let layoutConstant: CGFloat = self.constant.constraintConstantTargetValueFor(layoutAttribute: layoutToAttribute)
             
             // get layout to
-            #if os(iOS) || os(tvOS)
-            var layoutTo: AnyObject? = self.toItem.view ?? self.toItem.layoutSupport
-            #else
-            var layoutTo: AnyObject? = self.toItem.view
-            #endif
-            if layoutTo == nil && layoutToAttribute != .Width && layoutToAttribute != .Height {
-                layoutTo = installOnView
+            var layoutTo: AnyObject? = self.to.target
+            
+            // use superview if possible
+            if layoutTo == nil && layoutToAttribute != .width && layoutToAttribute != .height {
+                layoutTo = layoutFrom.superview
             }
             
             // create layout constraint
             let layoutConstraint = LayoutConstraint(
-                item: layoutFrom!,
+                item: layoutFrom,
                 attribute: layoutFromAttribute,
                 relatedBy: layoutRelation,
                 toItem: layoutTo,
                 attribute: layoutToAttribute,
-                multiplier: CGFloat(self.multiplier),
-                constant: layoutConstant)
-            layoutConstraint.identifier = self.label
+                multiplier: self.multiplier.constraintMultiplierTargetValue,
+                constant: layoutConstant
+            )
+            
+            // set label
+            layoutConstraint.label = self.label
             
             // set priority
-            layoutConstraint.priority = self.priority
+            layoutConstraint.priority = self.priority.constraintPriorityTargetValue
             
             // set constraint
-            layoutConstraint.snp_constraint = self
+            layoutConstraint.constraint = self
             
-            newLayoutConstraints.append(layoutConstraint)
+            // append
+            self.layoutConstraints.append(layoutConstraint)
         }
-        
-        // special logic for updating
-        if updateExisting {
-            // get existing constraints for this view
-            let existingLayoutConstraints = layoutFrom!.snp_installedLayoutConstraints.reverse()
-            
-            // 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(OSX)
-        if #available(iOS 8.0, *) {
-            NSLayoutConstraint.activateConstraints(newLayoutConstraints)
-        } else {
-            installOnView!.addConstraints(newLayoutConstraints)
-        }
-        #else
-            NSLayoutConstraint.activateConstraints(newLayoutConstraints)
-        #endif
-        
-        // set install info
-        self.installInfo = ConcreteConstraintInstallInfo(view: installOnView, layoutConstraints: NSHashTable.weakObjectsHashTable())
-        
-        // store which layout constraints are installed for this constraint
-        for layoutConstraint in newLayoutConstraints {
-            self.installInfo!.layoutConstraints.addObject(layoutConstraint)
-        }
-        
-        // store the layout constraints against the layout from view
-        layoutFrom!.snp_installedLayoutConstraints += newLayoutConstraints
-        
-        // return the new constraints
-        return newLayoutConstraints
     }
     
-    internal func uninstallFromView() {
-        if let installInfo = self.installInfo,
-            let installedLayoutConstraints = installInfo.layoutConstraints.allObjects as? [LayoutConstraint] {
-                
-                if installedLayoutConstraints.count > 0 {
-                    // remove the constraints from the UIView's storage
-                    #if SNAPKIT_DEPLOYMENT_LEGACY && !os(OSX)
-                    if #available(iOS 8.0, *) {
-                        NSLayoutConstraint.deactivateConstraints(installedLayoutConstraints)
-                    } else if let installedOnView = installInfo.view {
-                        installedOnView.removeConstraints(installedLayoutConstraints)
-                    }
-                    #else
-                        NSLayoutConstraint.deactivateConstraints(installedLayoutConstraints)
-                    #endif
-                    
-                    // remove the constraints from the from item view
-                    if let fromView = self.fromItem.view {
-                        fromView.snp_installedLayoutConstraints = fromView.snp_installedLayoutConstraints.filter {
-                            return !installedLayoutConstraints.contains($0)
-                        }
-                    }
-                }
-                
-        }
-        self.installInfo = nil
+    // MARK: Public
+    
+    public func activate() {
+        self.activateIfNeeded()
     }
     
-}
-
-private struct ConcreteConstraintInstallInfo {
+    public func deactivate() {
+        self.deactivateIfNeeded()
+    }
     
-    weak var view: View? = nil
-    let layoutConstraints: NSHashTable
+    @discardableResult
+    public func update(offset: ConstraintOffsetTarget) -> Constraint {
+        self.constant = offset.constraintOffsetTargetValue
+        return self
+    }
     
-}
-
-private extension NSLayoutAttribute {
+    @discardableResult
+    public func update(inset: ConstraintInsetTarget) -> Constraint {
+        self.constant = inset.constraintInsetTargetValue
+        return self
+    }
     
-    private func snp_constantForValue(value: Any?) -> CGFloat {
-        // Float
-        if let float = value as? Float {
-            return CGFloat(float)
-        }
-            // Double
-        else if let double = value as? Double {
-            return CGFloat(double)
-        }
-            // UInt
-        else if let int = value as? Int {
-            return CGFloat(int)
-        }
-            // Int
-        else if let uint = value as? UInt {
-            return CGFloat(uint)
-        }
-            // CGFloat
-        else if let float = value as? CGFloat {
-            return float
-        }
-            // CGSize
-        else if let size = value as? CGSize {
-            if self == .Width {
-                return size.width
-            } else if self == .Height {
-                return size.height
-            }
-        }
-            // CGPoint
-        else if let point = value as? CGPoint {
-            #if os(iOS) || os(tvOS)
-                switch self {
-                case .Left, .CenterX, .LeftMargin, .CenterXWithinMargins: return point.x
-                case .Top, .CenterY, .TopMargin, .CenterYWithinMargins, .LastBaseline, .FirstBaseline: return point.y
-                case .Right, .RightMargin: return point.x
-                case .Bottom, .BottomMargin: return point.y
-                case .Leading, .LeadingMargin: return point.x
-                case .Trailing, .TrailingMargin: return point.x
-                case .Width, .Height, .NotAnAttribute: return CGFloat(0)
-                }
-            #else
-                switch self {
-                case .Left, .CenterX: return point.x
-                case .Top, .CenterY, .LastBaseline: return point.y
-                case .Right: return point.x
-                case .Bottom: return point.y
-                case .Leading: return point.x
-                case .Trailing: return point.x
-                case .Width, .Height, .NotAnAttribute: return CGFloat(0)
-                case .FirstBaseline: return point.y
-                }
-            #endif
-        }
-            // EdgeInsets
-        else if let insets = value as? EdgeInsets {
-            #if os(iOS) || os(tvOS)
-                switch self {
-                case .Left, .CenterX, .LeftMargin, .CenterXWithinMargins: return insets.left
-                case .Top, .CenterY, .TopMargin, .CenterYWithinMargins, .LastBaseline, .FirstBaseline: return insets.top
-                case .Right, .RightMargin: return insets.right
-                case .Bottom, .BottomMargin: return insets.bottom
-                case .Leading, .LeadingMargin: return  (Config.interfaceLayoutDirection == .LeftToRight) ? insets.left : -insets.right
-                case .Trailing, .TrailingMargin: return  (Config.interfaceLayoutDirection == .LeftToRight) ? insets.right : -insets.left
-                case .Width: return -insets.left + insets.right
-                case .Height: return -insets.top + insets.bottom
-                case .NotAnAttribute: return CGFloat(0)
-                }
-            #else
-                switch self {
-                case .Left, .CenterX: return insets.left
-                case .Top, .CenterY, .LastBaseline: return insets.top
-                case .Right: return insets.right
-                case .Bottom: return insets.bottom
-                case .Leading: return  (Config.interfaceLayoutDirection == .LeftToRight) ? insets.left : -insets.right
-                case .Trailing: return  (Config.interfaceLayoutDirection == .LeftToRight) ? insets.right : -insets.left
-                case .Width: return -insets.left + insets.right
-                case .Height: return -insets.top + insets.bottom
-                case .NotAnAttribute: return CGFloat(0)
-                case .FirstBaseline: return insets.bottom
-                }
-            #endif
-        }
-        
-        return CGFloat(0);
+    @discardableResult
+    public func update(priority: ConstraintPriorityTarget) -> Constraint {
+        self.priority = priority.constraintPriorityTargetValue
+        return self
     }
-}
-
-private func closestCommonSuperviewFromView(fromView: View?, toView: View?) -> View? {
-    var views = Set<View>()
-    var fromView = fromView
-    var toView = toView
-    repeat {
-        if let view = toView {
-            if views.contains(view) {
-                return view
-            }
-            views.insert(view)
-            toView = view.superview
+    
+    @available(*, deprecated:0.40.0, message:"Use update(offset: ConstraintOffsetTarget) instead.")
+    public func updateOffset(amount: ConstraintOffsetTarget) -> Void { self.update(offset: amount) }
+    
+    @available(*, deprecated:0.40.0, message:"Use update(inset: ConstraintInsetTarget) instead.")
+    public func updateInsets(amount: ConstraintInsetTarget) -> Void { self.update(inset: amount) }
+    
+    @available(*, deprecated:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
+    public func updatePriority(amount: ConstraintPriorityTarget) -> Void { self.update(priority: amount) }
+    
+    @available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
+    public func updatePriorityRequired() -> Void {}
+    
+    @available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
+    public func updatePriorityHigh() -> Void { fatalError("Must be implemented by Concrete subclass.") }
+    
+    @available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
+    public func updatePriorityMedium() -> Void { fatalError("Must be implemented by Concrete subclass.") }
+    
+    @available(*, obsoleted:0.40.0, message:"Use update(priority: ConstraintPriorityTarget) instead.")
+    public func updatePriorityLow() -> Void { fatalError("Must be implemented by Concrete subclass.") }
+    
+    // MARK: Internal
+    
+    internal func updateConstantAndPriorityIfNeeded() {
+        for layoutConstraint in self.layoutConstraints {
+            let attribute = (layoutConstraint.secondAttribute == .notAnAttribute) ? layoutConstraint.firstAttribute : layoutConstraint.secondAttribute
+            layoutConstraint.constant = self.constant.constraintConstantTargetValueFor(layoutAttribute: attribute)
+            layoutConstraint.priority = self.priority.constraintPriorityTargetValue
         }
-        if let view = fromView {
-            if views.contains(view) {
-                return view
+    }
+    
+    internal func activateIfNeeded(updatingExisting: Bool = false) {
+        let view = self.from.view!
+        let layoutConstraints = self.layoutConstraints
+        let existingLayoutConstraints = view.snp.layoutConstraints
+        
+        if updatingExisting {
+            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)
             }
-            views.insert(view)
-            fromView = view.superview
+        } else {
+            NSLayoutConstraint.activate(layoutConstraints)
+            view.snp.add(layoutConstraints: layoutConstraints)
         }
-    } while (fromView != nil || toView != nil)
+    }
     
-    return nil
-}
-
-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)
+    internal func deactivateIfNeeded() {
+        let view = self.from.view!
+        let layoutConstraints = self.layoutConstraints
+        NSLayoutConstraint.deactivate(layoutConstraints)
+        view.snp.remove(layoutConstraints: layoutConstraints)
+    }
 }

+ 102 - 98
Source/ConstraintAttributes.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,15 +22,13 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to define `NSLayoutAttributes` in a more concise and composite manner
-*/
-internal struct ConstraintAttributes: OptionSetType, BooleanType {
+
+internal struct ConstraintAttributes: OptionSet {
     
     internal init(rawValue: UInt) {
         self.rawValue = rawValue
@@ -48,139 +46,145 @@ internal struct ConstraintAttributes: OptionSetType, BooleanType {
     internal var boolValue: Bool { return self.rawValue != 0 }
     
     internal func toRaw() -> UInt { return self.rawValue }
-    internal static func fromRaw(raw: UInt) -> ConstraintAttributes? { return self.init(raw) }
-    internal static func fromMask(raw: UInt) -> ConstraintAttributes { return self.init(raw) }
+    internal static func fromRaw(_ raw: UInt) -> ConstraintAttributes? { return self.init(raw) }
+    internal static func fromMask(_ raw: UInt) -> ConstraintAttributes { return self.init(raw) }
     
     // 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) }
-    @available(iOS 8.0, *)
-    internal static var LeftMargin: ConstraintAttributes { return self.init(4096) }
+    internal static var leftMargin: ConstraintAttributes { return self.init(4096) }
+    
     @available(iOS 8.0, *)
-    internal static var RightMargin: ConstraintAttributes { return self.init(8192) }
+    internal static var rightMargin: ConstraintAttributes { return self.init(8192) }
+    
     @available(iOS 8.0, *)
-    internal static var TopMargin: ConstraintAttributes { return self.init(16384) }
+    internal static var topMargin: ConstraintAttributes { return self.init(16384) }
+    
     @available(iOS 8.0, *)
-    internal static var BottomMargin: ConstraintAttributes { return self.init(32768) }
+    internal static var bottomMargin: ConstraintAttributes { return self.init(32768) }
+    
     @available(iOS 8.0, *)
-    internal static var LeadingMargin: ConstraintAttributes { return self.init(65536) }
+    internal static var leadingMargin: ConstraintAttributes { return self.init(65536) }
+    
     @available(iOS 8.0, *)
-    internal static var TrailingMargin: ConstraintAttributes { return self.init(131072) }
+    internal static var trailingMargin: ConstraintAttributes { return self.init(131072) }
+    
     @available(iOS 8.0, *)
-    internal static var CenterXWithinMargins: ConstraintAttributes { return self.init(262144) }
+    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)) {
-            attrs.append(.Left)
+        if (self.contains(ConstraintAttributes.left)) {
+            attrs.append(.left)
         }
-        if (self.contains(ConstraintAttributes.Top)) {
-            attrs.append(.Top)
+        if (self.contains(ConstraintAttributes.top)) {
+            attrs.append(.top)
         }
-        if (self.contains(ConstraintAttributes.Right)) {
-            attrs.append(.Right)
+        if (self.contains(ConstraintAttributes.right)) {
+            attrs.append(.right)
         }
-        if (self.contains(ConstraintAttributes.Bottom)) {
-            attrs.append(.Bottom)
+        if (self.contains(ConstraintAttributes.bottom)) {
+            attrs.append(.bottom)
         }
-        if (self.contains(ConstraintAttributes.Leading)) {
-            attrs.append(.Leading)
+        if (self.contains(ConstraintAttributes.leading)) {
+            attrs.append(.leading)
         }
-        if (self.contains(ConstraintAttributes.Trailing)) {
-            attrs.append(.Trailing)
+        if (self.contains(ConstraintAttributes.trailing)) {
+            attrs.append(.trailing)
         }
-        if (self.contains(ConstraintAttributes.Width)) {
-            attrs.append(.Width)
+        if (self.contains(ConstraintAttributes.width)) {
+            attrs.append(.width)
         }
-        if (self.contains(ConstraintAttributes.Height)) {
-            attrs.append(.Height)
+        if (self.contains(ConstraintAttributes.height)) {
+            attrs.append(.height)
         }
-        if (self.contains(ConstraintAttributes.CenterX)) {
-            attrs.append(.CenterX)
+        if (self.contains(ConstraintAttributes.centerX)) {
+            attrs.append(.centerX)
         }
-        if (self.contains(ConstraintAttributes.CenterY)) {
-            attrs.append(.CenterY)
+        if (self.contains(ConstraintAttributes.centerY)) {
+            attrs.append(.centerY)
         }
-        if (self.contains(ConstraintAttributes.Baseline)) {
-            #if swift(>=2.3)
-            attrs.append(.LastBaseline)
-            #else
-            attrs.append(.Baseline)
-            #endif
+        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)) {
-            attrs.append(.FirstBaseline)
-        }
-        if (self.contains(ConstraintAttributes.LeftMargin)) {
-            attrs.append(.LeftMargin)
-        }
-        if (self.contains(ConstraintAttributes.RightMargin)) {
-            attrs.append(.RightMargin)
-        }
-        if (self.contains(ConstraintAttributes.TopMargin)) {
-            attrs.append(.TopMargin)
-        }
-        if (self.contains(ConstraintAttributes.BottomMargin)) {
-            attrs.append(.BottomMargin)
-        }
-        if (self.contains(ConstraintAttributes.LeadingMargin)) {
-            attrs.append(.LeadingMargin)
-        }
-        if (self.contains(ConstraintAttributes.TrailingMargin)) {
-            attrs.append(.TrailingMargin)
-        }
-        if (self.contains(ConstraintAttributes.CenterXWithinMargins)) {
-            attrs.append(.CenterXWithinMargins)
-        }
-        if (self.contains(ConstraintAttributes.CenterYWithinMargins)) {
-            attrs.append(.CenterYWithinMargins)
-        }
+            if (self.contains(ConstraintAttributes.firstBaseline)) {
+                attrs.append(.firstBaseline)
+            }
+            if (self.contains(ConstraintAttributes.leftMargin)) {
+                attrs.append(.leftMargin)
+            }
+            if (self.contains(ConstraintAttributes.rightMargin)) {
+                attrs.append(.rightMargin)
+            }
+            if (self.contains(ConstraintAttributes.topMargin)) {
+                attrs.append(.topMargin)
+            }
+            if (self.contains(ConstraintAttributes.bottomMargin)) {
+                attrs.append(.bottomMargin)
+            }
+            if (self.contains(ConstraintAttributes.leadingMargin)) {
+                attrs.append(.leadingMargin)
+            }
+            if (self.contains(ConstraintAttributes.trailingMargin)) {
+                attrs.append(.trailingMargin)
+            }
+            if (self.contains(ConstraintAttributes.centerXWithinMargins)) {
+                attrs.append(.centerXWithinMargins)
+            }
+            if (self.contains(ConstraintAttributes.centerYWithinMargins)) {
+                attrs.append(.centerYWithinMargins)
+            }
         #endif
         
         return attrs
     }
 }
-internal func +=(inout left: ConstraintAttributes, right: ConstraintAttributes) {
-    left.unionInPlace(right)
+
+internal func + (left: ConstraintAttributes, right: ConstraintAttributes) -> ConstraintAttributes {
+    return left.union(right)
+}
+
+internal func +=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
+    left.formUnion(right)
 }
-internal func -=(inout left: ConstraintAttributes, right: ConstraintAttributes) {
-    left.subtractInPlace(right)
+
+internal func -=(left: inout ConstraintAttributes, right: ConstraintAttributes) {
+    left.subtract(right)
 }
+
 internal func ==(left: ConstraintAttributes, right: ConstraintAttributes) -> Bool {
     return left.rawValue == right.rawValue
 }

+ 9 - 14
Source/SnapKit.swift → Source/ConstraintConfig.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,21 +22,16 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
-public typealias InterfaceLayoutDirection = UIUserInterfaceLayoutDirection
-public typealias LayoutSupport = UILayoutSupport
+    import UIKit
+    public typealias ConstraintInterfaceLayoutDirection = UIUserInterfaceLayoutDirection
 #else
-import AppKit
-public typealias InterfaceLayoutDirection = NSUserInterfaceLayoutDirection
-public class LayoutSupport {}
+    import AppKit
+    public typealias ConstraintInterfaceLayoutDirection = NSUserInterfaceLayoutDirection
 #endif
 
-/**
-    Used to configure different parts of SnapKit
-*/
-public struct Config {
+
+public struct ConstraintConfig {
     
-    /// The interface layout direction
-    public static var interfaceLayoutDirection = InterfaceLayoutDirection.LeftToRight
+    public static var interfaceLayoutDirection: ConstraintInterfaceLayoutDirection = .leftToRight
     
-}
+}

+ 147 - 0
Source/ConstraintConstantTarget.swift

@@ -0,0 +1,147 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public protocol ConstraintConstantTarget {
+}
+
+extension CGPoint: ConstraintConstantTarget {
+}
+
+extension CGSize: ConstraintConstantTarget {    
+}
+
+extension ConstraintInsets: ConstraintConstantTarget {
+}
+
+extension ConstraintConstantTarget {
+    
+    internal func constraintConstantTargetValueFor(layoutAttribute: NSLayoutAttribute) -> CGFloat {
+        if let value = self as? CGFloat {
+            return value
+        }
+        
+        if let value = self as? Float {
+            return CGFloat(value)
+        }
+        
+        if let value = self as? Double {
+            return CGFloat(value)
+        }
+        
+        if let value = self as? Int {
+            return CGFloat(value)
+        }
+        
+        if let value = self as? UInt {
+            return CGFloat(value)
+        }
+        
+        if let value = self as? CGSize {
+            if layoutAttribute == .width {
+                return value.width
+            } else if layoutAttribute == .height {
+                return value.height
+            } else {
+                return 0.0
+            }
+        }
+        
+        if let value = self as? CGPoint {
+            #if os(iOS) || os(tvOS)
+                switch layoutAttribute {
+                case .left, .right, .leading, .trailing, .centerX, .leftMargin, .rightMargin, .leadingMargin, .trailingMargin, .centerXWithinMargins:
+                    return value.x
+                case .top, .bottom, .centerY, .topMargin, .bottomMargin, .centerYWithinMargins, .lastBaseline, .firstBaseline:
+                    return value.y
+                case .width, .height, .notAnAttribute:
+                    return 0.0
+                }
+            #else
+                switch layoutAttribute {
+                case .left, .right, .leading, .trailing, .centerX:
+                    return value.x
+                case .top, .bottom, .centerY, .lastBaseline, .firstBaseline:
+                    return value.y
+                case .width, .height, .notAnAttribute:
+                    return 0.0
+                }
+            #endif
+        }
+        
+        if let value = self as? ConstraintInsets {
+            #if os(iOS) || os(tvOS)
+                switch layoutAttribute {
+                case .left, .leftMargin, .centerX, .centerXWithinMargins:
+                    return value.left
+                case .top, .topMargin, .centerY, .centerYWithinMargins, .lastBaseline, .firstBaseline:
+                    return value.top
+                case .right, .rightMargin:
+                    return -value.right
+                case .bottom, .bottomMargin:
+                    return -value.bottom
+                case .leading, .leadingMargin:
+                    return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : -value.right
+                case .trailing, .trailingMargin:
+                    return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.right : -value.left
+                case .width:
+                    return -(value.left + value.right)
+                case .height:
+                    return -(value.top + value.bottom)
+                case .notAnAttribute:
+                    return 0.0
+                }
+            #else
+                switch layoutAttribute {
+                case .left, .centerX:
+                    return value.left
+                case .top, .centerY, .lastBaseline, .firstBaseline:
+                    return value.top
+                case .right:
+                    return -value.right
+                case .bottom:
+                    return -value.bottom
+                case .leading:
+                    return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.left : -value.right
+                case .trailing:
+                    return (ConstraintConfig.interfaceLayoutDirection == .leftToRight) ? value.right : -value.left
+                case .width:
+                    return -(value.left + value.right)
+                case .height:
+                    return -(value.top + value.bottom)
+                case .notAnAttribute:
+                    return 0.0
+                }
+            #endif
+        }
+        
+        return 0.0
+    }
+    
+}

+ 179 - 0
Source/ConstraintDSL.swift

@@ -0,0 +1,179 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public protocol ConstraintDSL {
+    
+    var label: String? { get set }
+    var target: AnyObject? { get }
+    
+}
+extension ConstraintDSL {
+    
+    public var label: String? {
+        get {
+            return objc_getAssociatedObject(self.target, &labelKey) as? String
+        }
+        set {
+            objc_setAssociatedObject(self.target, &labelKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
+        }
+    }
+    
+}
+private var labelKey: UInt8 = 0
+
+
+public protocol ConstraintAttributesDSL: ConstraintDSL {
+}
+extension ConstraintAttributesDSL {
+    
+    // MARK: Basics
+
+    public var left: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.left)
+    }
+    
+    public var top: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
+    }
+    
+    public var right: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.right)
+    }
+    
+    public var bottom: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
+    }
+    
+    public var leading: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leading)
+    }
+    
+    public var trailing: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailing)
+    }
+    
+    public var width: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.width)
+    }
+    
+    public var height: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
+    }
+    
+    public var centerX: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerX)
+    }
+    
+    public var centerY: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerY)
+    }
+    
+    public var edges: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.edges)
+    }
+    
+    public var size: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.size)
+    }
+    
+    public var center: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.center)
+    }
+    
+    // MARK: Baselines
+    
+    @available(*, deprecated:0.40.0, message:"Use .lastBaseline instead")
+    public var baseline: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
+    }
+    
+    @available(iOS 8.0, OSX 10.11, *)
+    public var lastBaseline: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.lastBaseline)
+    }
+    
+    @available(iOS 8.0, OSX 10.11, *)
+    public var firstBaseline: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.firstBaseline)
+    }
+    
+    // MARK: Margins
+    
+    @available(iOS 8.0, *)
+    public var leftMargin: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leftMargin)
+    }
+    
+    @available(iOS 8.0, *)
+    public var topMargin: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.topMargin)
+    }
+    
+    @available(iOS 8.0, *)
+    public var rightMargin: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.rightMargin)
+    }
+    
+    @available(iOS 8.0, *)
+    public var bottomMargin: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottomMargin)
+    }
+    
+    @available(iOS 8.0, *)
+    public var leadingMargin: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.leadingMargin)
+    }
+    
+    @available(iOS 8.0, *)
+    public var trailingMargin: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.trailingMargin)
+    }
+    
+    @available(iOS 8.0, *)
+    public var centerXWithinMargins: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerXWithinMargins)
+    }
+    
+    @available(iOS 8.0, *)
+    public var centerYWithinMargins: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerYWithinMargins)
+    }
+    
+    @available(iOS 8.0, *)
+    public var margins: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.margins)
+    }
+    
+    @available(iOS 8.0, *)
+    public var centerWithinMargins: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.centerWithinMargins)
+    }
+    
+}

+ 35 - 596
Source/ConstraintDescription.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,609 +22,48 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to expose the final API of a `ConstraintDescription` which allows getting a constraint from it
- */
-public protocol ConstraintDescriptionFinalizable: class {
-    
-    var constraint: Constraint { get }
-    
-    func labeled(label: String) -> ConstraintDescriptionFinalizable
-    
-}
-
-/**
-    Used to expose priority APIs
- */
-public protocol ConstraintDescriptionPriortizable: ConstraintDescriptionFinalizable {
-    
-    func priority(priority: Float) -> ConstraintDescriptionFinalizable
-    func priority(priority: Double) -> ConstraintDescriptionFinalizable
-    func priority(priority: CGFloat) -> ConstraintDescriptionFinalizable
-    func priority(priority: UInt) -> ConstraintDescriptionFinalizable
-    func priority(priority: Int) -> ConstraintDescriptionFinalizable
-    func priorityRequired() -> ConstraintDescriptionFinalizable
-    func priorityHigh() -> ConstraintDescriptionFinalizable
-    func priorityMedium() -> ConstraintDescriptionFinalizable
-    func priorityLow() -> ConstraintDescriptionFinalizable
-}
-
-/**
-    Used to expose multiplier & constant APIs
-*/
-public protocol ConstraintDescriptionEditable: ConstraintDescriptionPriortizable {
-
-    func multipliedBy(amount: Float) -> ConstraintDescriptionEditable
-    func multipliedBy(amount: Double) -> ConstraintDescriptionEditable
-    func multipliedBy(amount: CGFloat) -> ConstraintDescriptionEditable
-    func multipliedBy(amount: Int) -> ConstraintDescriptionEditable
-    func multipliedBy(amount: UInt) -> ConstraintDescriptionEditable
-    
-    func dividedBy(amount: Float) -> ConstraintDescriptionEditable
-    func dividedBy(amount: Double) -> ConstraintDescriptionEditable
-    func dividedBy(amount: CGFloat) -> ConstraintDescriptionEditable
-    func dividedBy(amount: Int) -> ConstraintDescriptionEditable
-    func dividedBy(amount: UInt) -> ConstraintDescriptionEditable
 
-    func offset(amount: Float) -> ConstraintDescriptionEditable
-    func offset(amount: Double) -> ConstraintDescriptionEditable
-    func offset(amount: CGFloat) -> ConstraintDescriptionEditable
-    func offset(amount: Int) -> ConstraintDescriptionEditable
-    func offset(amount: UInt) -> ConstraintDescriptionEditable
-    func offset(amount: CGPoint) -> ConstraintDescriptionEditable
-    func offset(amount: CGSize) -> ConstraintDescriptionEditable
-    func offset(amount: EdgeInsets) -> ConstraintDescriptionEditable
-    
-    func inset(amount: Float) -> ConstraintDescriptionEditable
-    func inset(amount: Double) -> ConstraintDescriptionEditable
-    func inset(amount: CGFloat) -> ConstraintDescriptionEditable
-    func inset(amount: Int) -> ConstraintDescriptionEditable
-    func inset(amount: UInt) -> ConstraintDescriptionEditable
-    func inset(amount: EdgeInsets) -> ConstraintDescriptionEditable
-}
-
-/**
-    Used to expose relation APIs
-*/
-public protocol ConstraintDescriptionRelatable: class {
-    
-    func equalTo(other: ConstraintItem) -> ConstraintDescriptionEditable
-    func equalTo(other: View) -> ConstraintDescriptionEditable
-    func equalToSuperview() -> ConstraintDescriptionEditable
-    @available(iOS 7.0, *)
-    func equalTo(other: LayoutSupport) -> ConstraintDescriptionEditable
-    @available(iOS 9.0, OSX 10.11, *)
-    func equalTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable
-    func equalTo(other: Float) -> ConstraintDescriptionEditable
-    func equalTo(other: Double) -> ConstraintDescriptionEditable
-    func equalTo(other: CGFloat) -> ConstraintDescriptionEditable
-    func equalTo(other: Int) -> ConstraintDescriptionEditable
-    func equalTo(other: UInt) -> ConstraintDescriptionEditable
-    func equalTo(other: CGSize) -> ConstraintDescriptionEditable
-    func equalTo(other: CGPoint) -> ConstraintDescriptionEditable
-    func equalTo(other: EdgeInsets) -> ConstraintDescriptionEditable
-    
-    func lessThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: View) -> ConstraintDescriptionEditable
-    func lessThanOrEqualToSuperview() -> ConstraintDescriptionEditable
-    @available(iOS 7.0, *)
-    func lessThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable
-    @available(iOS 9.0, OSX 10.11, *)
-    func lessThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable
-    func lessThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable
-    
-    func greaterThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: View) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualToSuperview() -> ConstraintDescriptionEditable
-    @available(iOS 7.0, *)
-    func greaterThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable
-    @available(iOS 9.0, OSX 10.11, *)
-    func greaterThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable
-    func greaterThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable
-
-}
-
-/**
-    Used to expose chaining APIs
-*/
-public protocol ConstraintDescriptionExtendable: ConstraintDescriptionRelatable {
-    
-    var left: ConstraintDescriptionExtendable { get }
-    var top: ConstraintDescriptionExtendable { get }
-    var bottom: ConstraintDescriptionExtendable { get }
-    var right: ConstraintDescriptionExtendable { get }
-    var leading: ConstraintDescriptionExtendable { get }
-    var trailing: ConstraintDescriptionExtendable { get }
-    var width: ConstraintDescriptionExtendable { get }
-    var height: ConstraintDescriptionExtendable { get }
-    var centerX: ConstraintDescriptionExtendable { get }
-    var centerY: ConstraintDescriptionExtendable { get }
-    var baseline: ConstraintDescriptionExtendable { get }
-    
-    @available(iOS 8.0, *)
-    var firstBaseline: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var leftMargin: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var rightMargin: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var topMargin: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var bottomMargin: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var leadingMargin: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var trailingMargin: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var centerXWithinMargins: ConstraintDescriptionExtendable { get }
-    @available(iOS 8.0, *)
-    var centerYWithinMargins: ConstraintDescriptionExtendable { get }
-}
-
-/**
-    Used to internally manage building constraint
- */
-internal class ConstraintDescription: ConstraintDescriptionExtendable, ConstraintDescriptionEditable, ConstraintDescriptionFinalizable {
-    
-    internal var left: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Left) }
-    internal var top: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Top) }
-    internal var right: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Right) }
-    internal var bottom: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Bottom) }
-    internal var leading: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Leading) }
-    internal var trailing: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Trailing) }
-    internal var width: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Width) }
-    internal var height: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Height) }
-    internal var centerX: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterX) }
-    internal var centerY: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterY) }
-    internal var baseline: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.Baseline) }
-    internal var label: String?
-    
-    @available(iOS 8.0, *)
-    internal var firstBaseline: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.FirstBaseline) }
-    @available(iOS 8.0, *)
-    internal var leftMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.LeftMargin) }
-    @available(iOS 8.0, *)
-    internal var rightMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.RightMargin) }
-    @available(iOS 8.0, *)
-    internal var topMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.TopMargin) }
-    @available(iOS 8.0, *)
-    internal var bottomMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.BottomMargin) }
-    @available(iOS 8.0, *)
-    internal var leadingMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.LeadingMargin) }
-    @available(iOS 8.0, *)
-    internal var trailingMargin: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.TrailingMargin) }
-    @available(iOS 8.0, *)
-    internal var centerXWithinMargins: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterXWithinMargins) }
-    @available(iOS 8.0, *)
-    internal var centerYWithinMargins: ConstraintDescriptionExtendable { return self.addConstraint(ConstraintAttributes.CenterYWithinMargins) }
-    
-    // MARK: initializer
-    
-    init(fromItem: ConstraintItem) {
-        self.fromItem = fromItem
-        self.toItem = ConstraintItem(object: nil, attributes: ConstraintAttributes.None)
-    }
-    
-    // MARK: equalTo
-    
-    internal func equalTo(other: ConstraintItem) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    internal func equalTo(other: View) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    internal func equalToSuperview() -> ConstraintDescriptionEditable {
-        guard let superview = fromItem.view?.superview else {
-            fatalError("equalToSuperview() requires the view have a superview before being set.")
-        }
-        
-        return self.equalTo(superview)
-    }
-    @available(iOS 7.0, *)
-    internal func equalTo(other: LayoutSupport) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    @available(iOS 9.0, OSX 10.11, *)
-    internal func equalTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    internal func equalTo(other: Float) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    internal func equalTo(other: Double) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .Equal)
-    }
-    internal func equalTo(other: CGFloat) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .Equal)
-    }
-    internal func equalTo(other: Int) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .Equal)
-    }
-    internal func equalTo(other: UInt) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .Equal)
-    }
-    internal func equalTo(other: CGSize) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    internal func equalTo(other: CGPoint) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    internal func equalTo(other: EdgeInsets) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .Equal)
-    }
-    
-    // MARK: lessThanOrEqualTo
-    
-    internal func lessThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: View) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualToSuperview() -> ConstraintDescriptionEditable {
-        guard let superview = fromItem.view?.superview else {
-            fatalError("lessThanOrEqualToSuperview() requires the view have a superview before being set.")
+public class ConstraintDescription {
+    
+    internal let view: ConstraintView
+    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
+    internal var priority: ConstraintPriorityTarget = 1000.0
+    internal lazy var constraint: Constraint? = {
+        guard let relation = self.relation,
+              let related = self.related,
+              let sourceLocation = self.sourceLocation else {
+            return nil
         }
+        let from = ConstraintItem(target: self.view, attributes: self.attributes)
         
-        return self.lessThanOrEqualTo(superview)
-    }
-    @available(iOS 7.0, *)
-    internal func lessThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    @available(iOS 9.0, OSX 10.11, *)
-    internal func lessThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func lessThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
+        return Constraint(
+            from: from,
+            to: related,
+            relation: relation,
+            sourceLocation: sourceLocation,
+            label: self.label,
+            multiplier: self.multiplier,
+            constant: self.constant,
+            priority: self.priority
+        )
+    }()
     
-    // MARK: greaterThanOrEqualTo
+    // MARK: Initialization
     
-    internal func greaterThanOrEqualTo(other: ConstraintItem) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: View) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualToSuperview() ->  ConstraintDescriptionEditable {
-        guard let superview = fromItem.view?.superview else {
-            fatalError("greaterThanOrEqualToSuperview() requires the view have a superview before being set.")
-        }
-        
-        return self.greaterThanOrEqualTo(superview)
-    }
-    @available(iOS 7.0, *)
-    internal func greaterThanOrEqualTo(other: LayoutSupport) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
-    }
-    @available(iOS 9.0, OSX 10.11, *)
-    internal func greaterThanOrEqualTo(other: NSLayoutAnchor) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .LessThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: Float) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: Double) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: CGFloat) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: Int) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: UInt) -> ConstraintDescriptionEditable {
-        return self.constrainTo(Float(other), relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: CGSize) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: CGPoint) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
-    }
-    internal func greaterThanOrEqualTo(other: EdgeInsets) -> ConstraintDescriptionEditable {
-        return self.constrainTo(other, relation: .GreaterThanOrEqualTo)
+    internal init(view: ConstraintView, attributes: ConstraintAttributes) {
+        self.view = view
+        self.attributes = attributes
     }
     
-    // MARK: multiplier
-    
-    internal func multipliedBy(amount: Float) -> ConstraintDescriptionEditable {
-        self.multiplier = amount
-        return self
-    }
-    internal func multipliedBy(amount: Double) -> ConstraintDescriptionEditable {
-        return self.multipliedBy(Float(amount))
-    }
-    internal func multipliedBy(amount: CGFloat) -> ConstraintDescriptionEditable {
-        return self.multipliedBy(Float(amount))
-    }
-    internal func multipliedBy(amount: Int) -> ConstraintDescriptionEditable {
-        return self.multipliedBy(Float(amount))
-    }
-    internal func multipliedBy(amount: UInt) -> ConstraintDescriptionEditable {
-        return self.multipliedBy(Float(amount))
-    }
-    
-    internal func dividedBy(amount: Float) -> ConstraintDescriptionEditable {
-        self.multiplier = 1.0 / amount;
-        return self
-    }
-    internal func dividedBy(amount: Double) -> ConstraintDescriptionEditable {
-        return self.dividedBy(Float(amount))
-    }
-    internal func dividedBy(amount: CGFloat) -> ConstraintDescriptionEditable {
-        return self.dividedBy(Float(amount))
-    }
-    internal func dividedBy(amount: Int) -> ConstraintDescriptionEditable {
-        return self.dividedBy(Float(amount))
-    }
-    internal func dividedBy(amount: UInt) -> ConstraintDescriptionEditable {
-        return self.dividedBy(Float(amount))
-    }
-    
-    // MARK: offset
-    
-    internal func offset(amount: Float) -> ConstraintDescriptionEditable {
-        self.constant = amount
-        return self
-    }
-    internal func offset(amount: Double) -> ConstraintDescriptionEditable {
-        return self.offset(Float(amount))
-    }
-    internal func offset(amount: CGFloat) -> ConstraintDescriptionEditable {
-        return self.offset(Float(amount))
-    }
-    internal func offset(amount: Int) -> ConstraintDescriptionEditable {
-        return self.offset(Float(amount))
-    }
-    internal func offset(amount: UInt) -> ConstraintDescriptionEditable {
-        return self.offset(Float(amount))
-    }
-    internal func offset(amount: CGPoint) -> ConstraintDescriptionEditable {
-        self.constant = amount
-        return self
-    }
-    internal func offset(amount: CGSize) -> ConstraintDescriptionEditable {
-        self.constant = amount
-        return self
-    }
-    internal func offset(amount: EdgeInsets) -> ConstraintDescriptionEditable {
-        self.constant = amount
-        return self
-    }
-    
-    // MARK: inset
-    
-    internal func inset(amount: Float) -> ConstraintDescriptionEditable {
-        let value = CGFloat(amount)
-        self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
-        return self
-    }
-    internal func inset(amount: Double) -> ConstraintDescriptionEditable {
-        let value = CGFloat(amount)
-        self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
-        return self
-    }
-    internal func inset(amount: CGFloat) -> ConstraintDescriptionEditable {
-        self.constant = EdgeInsets(top: amount, left: amount, bottom: -amount, right: -amount)
-        return self
-    }
-    internal func inset(amount: Int) -> ConstraintDescriptionEditable {
-        let value = CGFloat(amount)
-        self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
-        return self
-    }
-    internal func inset(amount: UInt) -> ConstraintDescriptionEditable {
-        let value = CGFloat(amount)
-        self.constant = EdgeInsets(top: value, left: value, bottom: -value, right: -value)
-        return self
-    }
-    internal func inset(amount: EdgeInsets) -> ConstraintDescriptionEditable {
-        self.constant = EdgeInsets(top: amount.top, left: amount.left, bottom: -amount.bottom, right: -amount.right)
-        return self
-    }
-    
-    // MARK: priority
-    
-    internal func priority(priority: Float) -> ConstraintDescriptionFinalizable {
-        self.priority = priority
-        return self
-    }
-    internal func priority(priority: Double) -> ConstraintDescriptionFinalizable {
-        return self.priority(Float(priority))
-    }
-    internal func priority(priority: CGFloat) -> ConstraintDescriptionFinalizable {
-        return self.priority(Float(priority))
-    }
-    func priority(priority: UInt) -> ConstraintDescriptionFinalizable {
-        return self.priority(Float(priority))
-    }
-    internal func priority(priority: Int) -> ConstraintDescriptionFinalizable {
-        return self.priority(Float(priority))
-    }
-    internal func priorityRequired() -> ConstraintDescriptionFinalizable {
-        return self.priority(1000.0)
-    }
-    internal func priorityHigh() -> ConstraintDescriptionFinalizable {
-        return self.priority(750.0)
-    }
-    internal func priorityMedium() -> ConstraintDescriptionFinalizable {
-        #if os(iOS) || os(tvOS)
-        return self.priority(500.0)
-        #else
-        return self.priority(501.0)
-        #endif
-    }
-    internal func priorityLow() -> ConstraintDescriptionFinalizable {
-        return self.priority(250.0)
-    }
-    
-    // MARK: Constraint
-    
-    internal var constraint: Constraint {
-        if self.concreteConstraint == nil {
-            if self.relation == nil {
-                fatalError("Attempting to create a constraint from a ConstraintDescription before it has been fully chained.")
-            }
-            self.concreteConstraint = ConcreteConstraint(
-                fromItem: self.fromItem,
-                toItem: self.toItem,
-                relation: self.relation!,
-                constant: self.constant,
-                multiplier: self.multiplier,
-                priority: self.priority,
-                label: self.label)
-        }
-        return self.concreteConstraint!
-    }
-    
-    func labeled(label: String) -> ConstraintDescriptionFinalizable {
-        self.label = label
-        return self
-    }
-    
-    // MARK: Private
-    
-    private let fromItem: ConstraintItem
-    private var toItem: ConstraintItem {
-        willSet {
-            if self.concreteConstraint != nil {
-                fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
-            }
-        }
-    }
-    private var relation: ConstraintRelation? {
-        willSet {
-            if self.concreteConstraint != nil {
-                fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
-            }
-        }
-    }
-    private var constant: Any = Float(0.0) {
-        willSet {
-            if self.concreteConstraint != nil {
-                fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
-            }
-        }
-    }
-    private var multiplier: Float = 1.0 {
-        willSet {
-            if self.concreteConstraint != nil {
-                fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
-            }
-        }
-    }
-    private var priority: Float = 1000.0 {
-        willSet {
-            if self.concreteConstraint != nil {
-                fatalError("Attempting to modify a ConstraintDescription after its constraint has been created.")
-            }
-        }
-    }
-    private var concreteConstraint: ConcreteConstraint? = nil
-    
-    private func addConstraint(attributes: ConstraintAttributes) -> ConstraintDescription {
-        if self.relation == nil {
-            self.fromItem.attributes += attributes
-        }
-        return self
-    }
-    
-    private func constrainTo(other: ConstraintItem, relation: ConstraintRelation) -> ConstraintDescription {
-        if other.attributes != ConstraintAttributes.None {
-            let toLayoutAttributes = other.attributes.layoutAttributes
-            if toLayoutAttributes.count > 1 {
-                let fromLayoutAttributes = self.fromItem.attributes.layoutAttributes
-                if toLayoutAttributes != fromLayoutAttributes {
-                    NSException(name: "Invalid Constraint", reason: "Cannot constrain to multiple non identical attributes", userInfo: nil).raise()
-                    return self
-                }
-                other.attributes = ConstraintAttributes.None
-            }
-        }
-        self.toItem = other
-        self.relation = relation
-        return self
-    }
-    
-    private func constrainTo(other: View, relation: ConstraintRelation) -> ConstraintDescription {
-        return constrainTo(ConstraintItem(object: other, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    @available(iOS 7.0, *)
-    private func constrainTo(other: LayoutSupport, relation: ConstraintRelation) -> ConstraintDescription {
-        return constrainTo(ConstraintItem(object: other, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    @available(iOS 9.0, OSX 10.11, *)
-    private func constrainTo(other: NSLayoutAnchor, relation: ConstraintRelation) -> ConstraintDescription {
-        return constrainTo(ConstraintItem(object: other, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    private func constrainTo(other: Float, relation: ConstraintRelation) -> ConstraintDescription {
-        self.constant = other
-        return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    private func constrainTo(other: Double, relation: ConstraintRelation) -> ConstraintDescription {
-        self.constant = other
-        return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    private func constrainTo(other: CGSize, relation: ConstraintRelation) -> ConstraintDescription {
-        self.constant = other
-        return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    private func constrainTo(other: CGPoint, relation: ConstraintRelation) -> ConstraintDescription {
-        self.constant = other
-        return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
-    }
-    
-    private func constrainTo(other: EdgeInsets, relation: ConstraintRelation) -> ConstraintDescription {
-        self.constant = other
-        return constrainTo(ConstraintItem(object: nil, attributes: ConstraintAttributes.None), relation: relation)
-    }
 }

+ 72 - 0
Source/ConstraintInsetTarget.swift

@@ -0,0 +1,72 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public protocol ConstraintInsetTarget: ConstraintConstantTarget {
+}
+
+extension Int: ConstraintInsetTarget {
+}
+
+extension UInt: ConstraintInsetTarget {
+}
+
+extension Float: ConstraintInsetTarget {
+}
+
+extension Double: ConstraintInsetTarget {
+}
+
+extension CGFloat: ConstraintInsetTarget {
+}
+
+extension ConstraintInsets: ConstraintInsetTarget {
+}
+
+extension ConstraintInsetTarget {
+
+    internal var constraintInsetTargetValue: ConstraintInsets {
+        if let amount = self as? ConstraintInsets {
+            return amount
+        } else if let amount = self as? Float {
+            return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
+        } else if let amount = self as? Double {
+            return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
+        } else if let amount = self as? CGFloat {
+            return ConstraintInsets(top: amount, left: amount, bottom: amount, right: amount)
+        } else if let amount = self as? Int {
+            return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
+        } else if let amount = self as? UInt {
+            return ConstraintInsets(top: CGFloat(amount), left: CGFloat(amount), bottom: CGFloat(amount), right: CGFloat(amount))
+        } else {
+            return ConstraintInsets(top: 0, left: 0, bottom: 0, right: 0)
+        }
+    }
+    
+}

+ 35 - 0
Source/ConstraintInsets.swift

@@ -0,0 +1,35 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+#if os(iOS) || os(tvOS)
+    public typealias ConstraintInsets = UIEdgeInsets
+#else
+    public typealias ConstraintInsets = EdgeInsets
+#endif

+ 24 - 31
Source/ConstraintItem.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,47 +22,40 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to assist in building a constraint
-*/
-public class ConstraintItem {
+
+public class ConstraintItem: Equatable {
+    
+    internal weak var target: AnyObject?
+    internal let attributes: ConstraintAttributes
     
-    internal init(object: AnyObject?, attributes: ConstraintAttributes) {
-        self.object = object
+    internal init(target: AnyObject?, attributes: ConstraintAttributes) {
+        self.target = target
         self.attributes = attributes
     }
     
-    internal weak var object: AnyObject?
-    internal var attributes: ConstraintAttributes
-    
-    internal var view: View? {
-        return self.object as? View
+    internal var view: ConstraintView? {
+        return self.target as? ConstraintView
     }
     
-    @available(iOS 7.0, *)
-    internal var layoutSupport: LayoutSupport? {
-        return self.object as? LayoutSupport
-    }
 }
 
-
-internal func ==(left: ConstraintItem, right: ConstraintItem) -> Bool {
-    if left.object == nil {
-        return false
+public func ==(lhs: ConstraintItem, rhs: ConstraintItem) -> Bool {
+    // pointer equality
+    guard lhs !== rhs else {
+        return true
     }
-    if right.object == nil {
-        return false
-    }
-    if left.object !== right.object {
-        return false
-    }
-    if left.attributes != right.attributes {
-        return false
+    
+    // must both have valid targets and identical attributes
+    guard let target1 = lhs.target,
+          let target2 = rhs.target,
+          target1 === target2 && lhs.attributes == rhs.attributes else {
+            return false
     }
+    
     return true
-}
+}

+ 36 - 0
Source/ConstraintLayoutGuide.swift

@@ -0,0 +1,36 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+#if os(iOS) || os(tvOS)
+    @available(iOS 9.0, *)
+    public typealias ConstraintLayoutGuide = UILayoutGuide
+#else
+    public class ConstraintLayoutGuide {}
+#endif

+ 45 - 0
Source/ConstraintLayoutGuideDSL.swift

@@ -0,0 +1,45 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+@available(iOS 9.0, *)
+public struct ConstraintLayoutGuideDSL: ConstraintAttributesDSL {
+    
+    public var target: AnyObject? {
+        return self.guide
+    }
+    
+    internal let guide: ConstraintLayoutGuide
+    
+    internal init(guide: ConstraintLayoutGuide) {
+        self.guide = guide
+        
+    }
+    
+}

+ 36 - 0
Source/ConstraintLayoutSupport.swift

@@ -0,0 +1,36 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+#if os(iOS) || os(tvOS)
+    @available(iOS 8.0, *)
+    public typealias ConstraintLayoutSupport = UILayoutSupport
+#else
+    public class ConstraintLayoutSupport {}
+#endif

+ 26 - 15
Source/ViewController+SnapKit.swift → Source/ConstraintLayoutSupportDSL.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,24 +22,35 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
+#else
+    import AppKit
+#endif
+
 
-/**
-    Used to expose public API on view controllers
-*/
-public extension UIViewController {
+@available(iOS 8.0, *)
+public struct ConstraintLayoutSupportDSL: ConstraintDSL {
     
-    /// top layout guide top
-    public var snp_topLayoutGuideTop: ConstraintItem { return ConstraintItem(object: self.topLayoutGuide, attributes: ConstraintAttributes.Top) }
+    public var target: AnyObject? {
+        return self.support
+    }
     
-    /// top layout guide bottom
-    public var snp_topLayoutGuideBottom: ConstraintItem { return ConstraintItem(object: self.topLayoutGuide, attributes: ConstraintAttributes.Bottom) }
+    internal let support: ConstraintLayoutSupport
     
-    /// bottom layout guide top
-    public var snp_bottomLayoutGuideTop: ConstraintItem { return ConstraintItem(object: self.bottomLayoutGuide, attributes: ConstraintAttributes.Top) }
+    internal init(support: ConstraintLayoutSupport) {
+        self.support = support
+        
+    }
     
-    /// bottom layout guide bottom
-    public var snp_bottomLayoutGuideBottom: ConstraintItem { return ConstraintItem(object: self.bottomLayoutGuide, attributes: ConstraintAttributes.Bottom) }
+    public var top: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.top)
+    }
     
+    public var bottom: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.bottom)
+    }
+    
+    public var height: ConstraintItem {
+        return ConstraintItem(target: self.target, attributes: ConstraintAttributes.height)
+    }
 }
-#endif

+ 123 - 113
Source/ConstraintMaker.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,175 +22,185 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to make constraints
-*/
 public class ConstraintMaker {
     
-    /// left edge
-    public var left: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Left) }
+    public var left: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.left)
+    }
     
-    /// top edge
-    public var top: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Top) }
+    public var top: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.top)
+    }
     
-    /// right edge
-    public var right: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Right) }
+    public var bottom: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.bottom)
+    }
     
-    /// bottom edge
-    public var bottom: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Bottom) }
+    public var right: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.right)
+    }
     
-    /// leading edge
-    public var leading: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Leading) }
+    public var leading: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.leading)
+    }
     
-    /// trailing edge
-    public var trailing: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Trailing) }
+    public var trailing: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.trailing)
+    }
     
-    /// width dimension
-    public var width: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Width) }
+    public var width: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.width)
+    }
     
-    /// height dimension
-    public var height: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Height) }
+    public var height: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.height)
+    }
     
-    /// centerX dimension
-    public var centerX: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterX) }
+    public var centerX: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.centerX)
+    }
     
-    /// centerY dimension
-    public var centerY: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterY) }
+    public var centerY: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.centerY)
+    }
     
-    /// baseline position
-    public var baseline: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Baseline) }
+    @available(*, deprecated:0.40.0, message:"Use lastBaseline instead")
+    public var baseline: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.lastBaseline)
+    }
     
-    /// firse baseline position
-    @available(iOS 8.0, *)
-    public var firstBaseline: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.FirstBaseline) }
+    public var lastBaseline: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.lastBaseline)
+    }
     
-    /// left margin
-    @available(iOS 8.0, *)
-    public var leftMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.LeftMargin) }
+    @available(iOS 8.0, OSX 10.11, *)
+    public var firstBaseline: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.firstBaseline)
+    }
     
-    /// right margin
     @available(iOS 8.0, *)
-    public var rightMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.RightMargin) }
+    public var leftMargin: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.leftMargin)
+    }
     
-    /// top margin
     @available(iOS 8.0, *)
-    public var topMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.TopMargin) }
+    public var rightMargin: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.rightMargin)
+    }
     
-    /// bottom margin
     @available(iOS 8.0, *)
-    public var bottomMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.BottomMargin) }
+    public var bottomMargin: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.bottomMargin)
+    }
     
-    /// leading margin
     @available(iOS 8.0, *)
-    public var leadingMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.LeadingMargin) }
+    public var leadingMargin: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.leadingMargin)
+    }
     
-    /// trailing margin
     @available(iOS 8.0, *)
-    public var trailingMargin: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.TrailingMargin) }
+    public var trailingMargin: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.trailingMargin)
+    }
     
-    /// centerX within margins
     @available(iOS 8.0, *)
-    public var centerXWithinMargins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterXWithinMargins) }
+    public var centerXWithinMargins: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.centerXWithinMargins)
+    }
     
-    /// centerY within margins
     @available(iOS 8.0, *)
-    public var centerYWithinMargins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterYWithinMargins) }
-    
-    /// top + left + bottom + right edges
-    public var edges: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Edges) }
-    
-    /// width + height dimensions
-    public var size: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Size) }
+    public var centerYWithinMargins: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.centerYWithinMargins)
+    }
     
-    // centerX + centerY positions
-    public var center: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Center) }
+    public var edges: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.edges)
+    }
+    public var size: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.size)
+    }
+    public var center: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.center)
+    }
     
-    // top + left + bottom + right margins
     @available(iOS 8.0, *)
-    public var margins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.Margins) }
+    public var margins: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.margins)
+    }
     
-    // centerX + centerY within margins
     @available(iOS 8.0, *)
-    public var centerWithinMargins: ConstraintDescriptionExtendable { return self.makeConstraintDescription(ConstraintAttributes.CenterWithinMargins) }
+    public var centerWithinMargins: ConstraintMakerExtendable {
+        return self.makeExtendableWithAttributes(.centerWithinMargins)
+    }
     
-    internal init(view: View, file: String, line: UInt) {
+    private let view: ConstraintView
+    private var descriptions = [ConstraintDescription]()
+    
+    internal init(view: ConstraintView) {
         self.view = view
-        self.file = file
-        self.line = line
+        self.view.translatesAutoresizingMaskIntoConstraints = false
     }
     
-    internal let file: String
-    internal let line: UInt
-    internal let view: View
-    internal var constraintDescriptions = [ConstraintDescription]()
-    
-    internal func makeConstraintDescription(attributes: ConstraintAttributes) -> ConstraintDescription {
-        let item = ConstraintItem(object: self.view, attributes: attributes)
-        let constraintDescription = ConstraintDescription(fromItem: item)
-        self.constraintDescriptions.append(constraintDescription)
-        return constraintDescription
+    internal func makeExtendableWithAttributes(_ attributes: ConstraintAttributes) -> ConstraintMakerExtendable {
+        let description = ConstraintDescription(view: self.view, attributes: attributes)
+        self.descriptions.append(description)
+        return ConstraintMakerExtendable(description)
     }
     
-    internal class func prepareConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) -> [Constraint] {
-        let maker = ConstraintMaker(view: view, file: file, line: line)
-        closure(make: maker)
-        
-        let constraints = maker.constraintDescriptions.map { $0.constraint }
-        for constraint in constraints {
-            constraint.makerFile = maker.file
-            constraint.makerLine = maker.line
-        }
+    internal static func prepareConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
+        let maker = ConstraintMaker(view: view)
+        closure(maker)
+        let constraints = maker.descriptions
+            .map { $0.constraint }
+            .filter { $0 != nil }
+            .map { $0! }
         return constraints
     }
     
-    internal class func makeConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) {
-        view.translatesAutoresizingMaskIntoConstraints = false
-        let maker = ConstraintMaker(view: view, file: file, line: line)
-        closure(make: maker)
-        
-        let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint }
+    internal static func makeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
+        let maker = ConstraintMaker(view: view)
+        closure(maker)
+        let constraints = maker.descriptions
+            .map { $0.constraint }
+            .filter { $0 != nil }
+            .map { $0! }
         for constraint in constraints {
-            constraint.makerFile = maker.file
-            constraint.makerLine = maker.line
-            constraint.installOnView(updateExisting: false)
+            constraint.activateIfNeeded(updatingExisting: false)
         }
     }
     
-    internal class func remakeConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) {
-        view.translatesAutoresizingMaskIntoConstraints = false
-        let maker = ConstraintMaker(view: view, file: file, line: line)
-        closure(make: maker)
-        
+    internal static func remakeConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
         self.removeConstraints(view: view)
-        let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint }
-        for constraint in constraints {
-            constraint.makerFile = maker.file
-            constraint.makerLine = maker.line
-            constraint.installOnView(updateExisting: false)
-        }
+        self.makeConstraints(view: view, closure: closure)
     }
     
-    internal class func updateConstraints(view view: View, file: String = "Unknown", line: UInt = 0, @noescape closure: (make: ConstraintMaker) -> Void) {
-        view.translatesAutoresizingMaskIntoConstraints = false
-        let maker = ConstraintMaker(view: view, file: file, line: line)
-        closure(make: maker)
+    internal static func updateConstraints(view: ConstraintView, closure: (_ make: ConstraintMaker) -> Void) {
+        guard view.snp.layoutConstraints.count > 0 else {
+            self.makeConstraints(view: view, closure: closure)
+            return
+        }
         
-        let constraints = maker.constraintDescriptions.map { $0.constraint as! ConcreteConstraint}
+        let maker = ConstraintMaker(view: view)
+        closure(maker)
+        let constraints = maker.descriptions
+            .map { $0.constraint }
+            .filter { $0 != nil }
+            .map { $0! }
         for constraint in constraints {
-            constraint.makerFile = maker.file
-            constraint.makerLine = maker.line
-            constraint.installOnView(updateExisting: true)
+            constraint.activateIfNeeded(updatingExisting: true)
         }
     }
     
-    internal class func removeConstraints(view view: View) {
-        for existingLayoutConstraint in view.snp_installedLayoutConstraints {
-            existingLayoutConstraint.snp_constraint?.uninstall()
+    internal static func removeConstraints(view: ConstraintView) {
+        let constraints = view.snp.layoutConstraints.map { $0.constraint! }
+        for constraint in constraints {
+            constraint.deactivateIfNeeded()
         }
     }
+    
 }

+ 56 - 0
Source/ConstraintMakerEditable.swift

@@ -0,0 +1,56 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public class ConstraintMakerEditable: ConstraintMakerPriortizable {
+
+    @discardableResult
+    public func multipliedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
+        self.description.multiplier = amount
+        return self
+    }
+    
+    @discardableResult
+    public func dividedBy(_ amount: ConstraintMultiplierTarget) -> ConstraintMakerEditable {
+        return self.multipliedBy(1.0 / amount.constraintMultiplierTargetValue)
+    }
+    
+    @discardableResult
+    public func offset(_ amount: ConstraintOffsetTarget) -> ConstraintMakerEditable {
+        self.description.constant = amount.constraintOffsetTargetValue
+        return self
+    }
+    
+    @discardableResult
+    public func inset(_ amount: ConstraintInsetTarget) -> ConstraintMakerEditable {
+        self.description.constant = amount.constraintInsetTargetValue
+        return self
+    }
+    
+}

+ 163 - 0
Source/ConstraintMakerExtendable.swift

@@ -0,0 +1,163 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public class ConstraintMakerExtendable: ConstraintMakerRelatable {
+    
+    public var left: ConstraintMakerExtendable {
+        self.description.attributes += .left
+        return self
+    }
+    
+    public var top: ConstraintMakerExtendable {
+        self.description.attributes += .top
+        return self
+    }
+    
+    public var bottom: ConstraintMakerExtendable {
+        self.description.attributes += .bottom
+        return self
+    }
+    
+    public var right: ConstraintMakerExtendable {
+        self.description.attributes += .right
+        return self
+    }
+    
+    public var leading: ConstraintMakerExtendable {
+        self.description.attributes += .leading
+        return self
+    }
+    
+    public var trailing: ConstraintMakerExtendable {
+        self.description.attributes += .trailing
+        return self
+    }
+    
+    public var width: ConstraintMakerExtendable {
+        self.description.attributes += .width
+        return self
+    }
+    
+    public var height: ConstraintMakerExtendable {
+        self.description.attributes += .height
+        return self
+    }
+    
+    public var centerX: ConstraintMakerExtendable {
+        self.description.attributes += .centerX
+        return self
+    }
+    
+    public var centerY: ConstraintMakerExtendable {
+        self.description.attributes += .centerY
+        return self
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use lastBaseline instead")
+    public var baseline: ConstraintMakerExtendable {
+        self.description.attributes += .lastBaseline
+        return self
+    }
+    
+    public var lastBaseline: ConstraintMakerExtendable {
+        self.description.attributes += .lastBaseline
+        return self
+    }
+    
+    @available(iOS 8.0, OSX 10.11, *)
+    public var firstBaseline: ConstraintMakerExtendable {
+        self.description.attributes += .firstBaseline
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var leftMargin: ConstraintMakerExtendable {
+        self.description.attributes += .leftMargin
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var rightMargin: ConstraintMakerExtendable {
+        self.description.attributes += .rightMargin
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var bottomMargin: ConstraintMakerExtendable {
+        self.description.attributes += .bottomMargin
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var leadingMargin: ConstraintMakerExtendable {
+        self.description.attributes += .leadingMargin
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var trailingMargin: ConstraintMakerExtendable {
+        self.description.attributes += .trailingMargin
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var centerXWithinMargins: ConstraintMakerExtendable {
+        self.description.attributes += .centerXWithinMargins
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var centerYWithinMargins: ConstraintMakerExtendable {
+        self.description.attributes += .centerYWithinMargins
+        return self
+    }
+    
+    public var edges: ConstraintMakerExtendable {
+        self.description.attributes += .edges
+        return self
+    }
+    public var size: ConstraintMakerExtendable {
+        self.description.attributes += .size
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var margins: ConstraintMakerExtendable {
+        self.description.attributes += .margins
+        return self
+    }
+    
+    @available(iOS 8.0, *)
+    public var centerWithinMargins: ConstraintMakerExtendable {
+        self.description.attributes += .centerWithinMargins
+        return self
+    }
+    
+}

+ 49 - 0
Source/ConstraintMakerFinalizable.swift

@@ -0,0 +1,49 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public class ConstraintMakerFinalizable {
+    
+    internal let description: ConstraintDescription
+    
+    internal init(_ description: ConstraintDescription) {
+        self.description = description
+    }
+    
+    @discardableResult
+    public func labeled(_ label: String) -> ConstraintMakerFinalizable {
+        self.description.label = label
+        return self
+    }
+    
+    public var constraint: Constraint {
+        return self.description.constraint!
+    }
+    
+}

+ 67 - 0
Source/ConstraintMakerPriortizable.swift

@@ -0,0 +1,67 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public class ConstraintMakerPriortizable: ConstraintMakerFinalizable {
+    
+    @discardableResult
+    public func priority(_ amount: ConstraintPriorityTarget) -> ConstraintMakerFinalizable {
+        self.description.priority = amount
+        return self
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
+    @discardableResult
+    public func priorityRequired() -> ConstraintMakerFinalizable {
+        return self.priority(1000)
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
+    @discardableResult
+    public func priorityHigh() -> ConstraintMakerFinalizable {
+        return self.priority(750)
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
+    @discardableResult
+    public func priorityMedium() -> ConstraintMakerFinalizable {
+        #if os(iOS) || os(tvOS)
+            return self.priority(500)
+        #else
+            return self.priority(501)
+        #endif
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use priority(_ amount: ConstraintPriorityTarget) instead.")
+    @discardableResult
+    public func priorityLow() -> ConstraintMakerFinalizable {
+        return self.priority(250)
+    }
+    
+}

+ 95 - 0
Source/ConstraintMakerRelatable.swift

@@ -0,0 +1,95 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public class ConstraintMakerRelatable {
+    
+    internal let description: ConstraintDescription
+    
+    internal init(_ description: ConstraintDescription) {
+        self.description = description
+    }
+    
+    internal func relatedTo(_ other: ConstraintRelatableTarget, relation: ConstraintRelation, file: String, line: UInt) -> ConstraintMakerEditable {
+        let related: ConstraintItem
+        let constant: ConstraintConstantTarget
+        
+        if let other = other as? ConstraintItem {
+            guard other.attributes == ConstraintAttributes.none ||
+                  other.attributes.layoutAttributes.count <= 1 ||
+                  other.attributes.layoutAttributes == self.description.attributes.layoutAttributes ||
+                  other.attributes == .edges && self.description.attributes == .margins ||
+                  other.attributes == .margins && self.description.attributes == .edges else {
+                fatalError("Cannot constraint to multiple non identical attributes. (\(file), \(line))");
+            }
+            
+            related = other
+            constant = 0.0
+        } else if let other = other as? ConstraintView {
+            related = ConstraintItem(target: other, attributes: ConstraintAttributes.none)
+            constant = 0.0
+        } else if let other = other as? ConstraintConstantTarget {
+            related = ConstraintItem(target: nil, attributes: ConstraintAttributes.none)
+            constant = other
+        } else {
+            fatalError("Invalid constraint. (\(file), \(line))")
+        }
+        
+        let editable = ConstraintMakerEditable(self.description)
+        editable.description.sourceLocation = (file, line)
+        editable.description.relation = relation
+        editable.description.related = related
+        editable.description.constant = constant
+        return editable
+    }
+    
+    @discardableResult
+    public func equalTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
+        return self.relatedTo(other, relation: .equal, file: file, line: line)
+    }
+    
+    @discardableResult
+    public func equalToSuperview(_ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
+        guard let other = self.description.view.superview else {
+            fatalError("Expected superview but found nil when attempting make constraint `equalToSuperview`.")
+        }
+        return self.relatedTo(other, relation: .equal, file: file, line: line)
+    }
+    
+    @discardableResult
+    public func lessThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, _ line: UInt = #line) -> ConstraintMakerEditable {
+        return self.relatedTo(other, relation: .lessThanOrEqual, file: file, line: line)
+    }
+    
+    @discardableResult
+    public func greaterThanOrEqualTo(_ other: ConstraintRelatableTarget, _ file: String = #file, line: UInt = #line) -> ConstraintMakerEditable {
+        return self.relatedTo(other, relation: .greaterThanOrEqual, file: file, line: line)
+    }
+    
+}

+ 75 - 0
Source/ConstraintMultiplierTarget.swift

@@ -0,0 +1,75 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public protocol ConstraintMultiplierTarget {
+    
+    var constraintMultiplierTargetValue: CGFloat { get }
+    
+}
+
+extension Int: ConstraintMultiplierTarget {
+    
+    public var constraintMultiplierTargetValue: CGFloat {
+        return CGFloat(self)
+    }
+    
+}
+
+extension UInt: ConstraintMultiplierTarget {
+    
+    public var constraintMultiplierTargetValue: CGFloat {
+        return CGFloat(self)
+    }
+    
+}
+
+extension Float: ConstraintMultiplierTarget {
+    
+    public var constraintMultiplierTargetValue: CGFloat {
+        return CGFloat(self)
+    }
+    
+}
+
+extension Double: ConstraintMultiplierTarget {
+    
+    public var constraintMultiplierTargetValue: CGFloat {
+        return CGFloat(self)
+    }
+    
+}
+
+extension CGFloat: ConstraintMultiplierTarget {
+    
+    public var constraintMultiplierTargetValue: CGFloat {
+        return self
+    }
+    
+}

+ 69 - 0
Source/ConstraintOffsetTarget.swift

@@ -0,0 +1,69 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public protocol ConstraintOffsetTarget: ConstraintConstantTarget {
+}
+
+extension Int: ConstraintOffsetTarget {
+}
+
+extension UInt: ConstraintOffsetTarget {
+}
+
+extension Float: ConstraintOffsetTarget {
+}
+
+extension Double: ConstraintOffsetTarget {
+}
+
+extension CGFloat: ConstraintOffsetTarget {
+}
+
+extension ConstraintOffsetTarget {
+    
+    internal var constraintOffsetTargetValue: CGFloat {
+        let offset: CGFloat
+        if let amount = self as? Float {
+            offset = CGFloat(amount)
+        } else if let amount = self as? Double {
+            offset = CGFloat(amount)
+        } else if let amount = self as? CGFloat {
+            offset = CGFloat(amount)
+        } else if let amount = self as? Int {
+            offset = CGFloat(amount)
+        } else if let amount = self as? UInt {
+            offset = CGFloat(amount)
+        } else {
+            offset = 0.0
+        }
+        return offset
+    }
+    
+}

+ 75 - 0
Source/ConstraintPriorityTarget.swift

@@ -0,0 +1,75 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public protocol ConstraintPriorityTarget {
+    
+    var constraintPriorityTargetValue: Float { get }
+    
+}
+
+extension Int: ConstraintPriorityTarget {
+    
+    public var constraintPriorityTargetValue: Float {
+        return Float(self)
+    }
+    
+}
+
+extension UInt: ConstraintPriorityTarget {
+    
+    public var constraintPriorityTargetValue: Float {
+        return Float(self)
+    }
+    
+}
+
+extension Float: ConstraintPriorityTarget {
+    
+    public var constraintPriorityTargetValue: Float {
+        return self
+    }
+    
+}
+
+extension Double: ConstraintPriorityTarget {
+    
+    public var constraintPriorityTargetValue: Float {
+        return Float(self)
+    }
+    
+}
+
+extension CGFloat: ConstraintPriorityTarget {
+    
+    public var constraintPriorityTargetValue: Float {
+        return Float(self)
+    }
+    
+}

+ 37 - 13
Source/EdgeInsets.swift → Source/ConstraintRelatableTarget.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,17 +22,41 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
-public typealias EdgeInsets = UIEdgeInsets
-public func EdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> EdgeInsets {
-    return EdgeInsets(top: top, left: left, bottom: bottom, right: right)
-}
-public let EdgeInsetsZero = EdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+    import UIKit
 #else
-import AppKit
-public typealias EdgeInsets = NSEdgeInsets
-public func EdgeInsetsMake(top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> EdgeInsets {
-    return EdgeInsets(top: top, left: left, bottom: bottom, right: right)
-}
-public let EdgeInsetsZero = EdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+    import AppKit
 #endif
+
+
+public protocol ConstraintRelatableTarget {
+}
+
+extension Int: ConstraintRelatableTarget {
+}
+
+extension UInt: ConstraintRelatableTarget {
+}
+
+extension Float: ConstraintRelatableTarget {
+}
+
+extension Double: ConstraintRelatableTarget {
+}
+
+extension CGFloat: ConstraintRelatableTarget {
+}
+
+extension CGSize: ConstraintRelatableTarget {
+}
+
+extension CGPoint: ConstraintRelatableTarget {
+}
+
+extension ConstraintInsets: ConstraintRelatableTarget {
+}
+
+extension ConstraintItem: ConstraintRelatableTarget {
+}
+
+extension ConstraintView: ConstraintRelatableTarget {
+}

+ 14 - 14
Source/ConstraintRelation.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,27 +22,27 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to define `NSLayoutRelation`
-*/
+
 internal enum ConstraintRelation: Int {
-    case Equal = 1, LessThanOrEqualTo, GreaterThanOrEqualTo
+    case equal = 1
+    case lessThanOrEqual
+    case greaterThanOrEqual
     
     internal var layoutRelation: NSLayoutRelation {
         get {
             switch(self) {
-            case .LessThanOrEqualTo:
-                return .LessThanOrEqual
-            case .GreaterThanOrEqualTo:
-                return .GreaterThanOrEqual
-            default:
-                return .Equal
+            case .equal:
+                return .equal
+            case .lessThanOrEqual:
+                return .lessThanOrEqual
+            case .greaterThanOrEqual:
+                return .greaterThanOrEqual
             }
         }
     }
-}
+}

+ 152 - 0
Source/ConstraintView+Extensions.swift

@@ -0,0 +1,152 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public extension ConstraintView {
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_top: ConstraintItem { return self.snp.top }
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_bottom: ConstraintItem { return self.snp.bottom }
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_trailing: ConstraintItem { return self.snp.trailing }
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_height: ConstraintItem { return self.snp.height }
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_centerY: ConstraintItem { return self.snp.centerY }
+    
+    @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:"Use newer snp.* syntax.")
+    @available(iOS 8.0, OSX 10.11, *)
+    public var snp_lastBaseline: ConstraintItem { return self.snp.lastBaseline }
+    
+    @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:"Use newer snp.* syntax.")
+    @available(iOS 8.0, *)
+    public var snp_leftMargin: ConstraintItem { return self.snp.leftMargin }
+    
+    @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:"Use newer snp.* syntax.")
+    @available(iOS 8.0, *)
+    public var snp_rightMargin: ConstraintItem { return self.snp.rightMargin }
+    
+    @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:"Use newer snp.* syntax.")
+    @available(iOS 8.0, *)
+    public var snp_leadingMargin: ConstraintItem { return self.snp.leadingMargin }
+    
+    @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:"Use newer snp.* syntax.")
+    @available(iOS 8.0, *)
+    public var snp_centerXWithinMargins: ConstraintItem { return self.snp.centerXWithinMargins }
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_edges: ConstraintItem { return self.snp.edges }
+    
+    @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:"Use newer snp.* syntax.")
+    public var snp_center: ConstraintItem { return self.snp.center }
+    
+    @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:"Use newer snp.* syntax.")
+    @available(iOS 8.0, *)
+    public var snp_centerWithinMargins: ConstraintItem { return self.snp.centerWithinMargins }
+    
+    @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
+    public func snp_prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
+        return self.snp.prepareConstraints(closure)
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
+    public func snp_makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        self.snp.makeConstraints(closure)
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
+    public func snp_remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        self.snp.remakeConstraints(closure)
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
+    public func snp_updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        self.snp.updateConstraints(closure)
+    }
+    
+    @available(*, deprecated:0.40.0, message:"Use newer snp.* syntax.")
+    public func snp_removeConstraints() {
+        self.snp.removeConstraints()
+    }
+    
+    public var snp: ConstraintViewDSL {
+        return ConstraintViewDSL(view: self)
+    }
+    
+}

+ 35 - 0
Source/ConstraintView.swift

@@ -0,0 +1,35 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+#if os(iOS) || os(tvOS)
+    public typealias ConstraintView = UIView
+#else
+    public typealias ConstraintView = NSView
+#endif

+ 135 - 0
Source/ConstraintViewDSL.swift

@@ -0,0 +1,135 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#else
+    import AppKit
+#endif
+
+
+public struct ConstraintViewDSL: ConstraintAttributesDSL {
+    
+    @discardableResult
+    public func prepareConstraints(_ closure: (_ make: ConstraintMaker) -> Void) -> [Constraint] {
+        return ConstraintMaker.prepareConstraints(view: self.view, closure: closure)
+    }
+    
+    public func makeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        ConstraintMaker.makeConstraints(view: self.view, closure: closure)
+    }
+    
+    public func remakeConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        ConstraintMaker.remakeConstraints(view: self.view, closure: closure)
+    }
+    
+    public func updateConstraints(_ closure: (_ make: ConstraintMaker) -> Void) {
+        ConstraintMaker.updateConstraints(view: self.view, closure: closure)
+    }
+    
+    public func removeConstraints() {
+        ConstraintMaker.removeConstraints(view: self.view)
+    }
+    
+    
+    
+    public var contentHuggingHorizontalPriority: Float {
+        get {
+            return self.view.contentHuggingPriority(for: .horizontal)
+        }
+        set {
+            self.view.setContentHuggingPriority(newValue, for: .horizontal)
+        }
+    }
+    
+    public var contentHuggingVerticalPriority: Float {
+        get {
+            return self.view.contentHuggingPriority(for: .vertical)
+        }
+        set {
+            self.view.setContentHuggingPriority(newValue, for: .vertical)
+        }
+    }
+    
+    public var contentCompressionResistanceHorizontalPriority: Float {
+        get {
+            return self.view.contentCompressionResistancePriority(for: .horizontal)
+        }
+        set {
+            self.view.setContentHuggingPriority(newValue, for: .horizontal)
+        }
+    }
+    
+    public var contentCompressionResistanceVerticalPriority: Float {
+        get {
+            return self.view.contentCompressionResistancePriority(for: .vertical)
+        }
+        set {
+            self.view.setContentCompressionResistancePriority(newValue, for: .vertical)
+        }
+    }
+    
+    public var target: AnyObject? {
+        return self.view
+    }
+    
+    internal let view: ConstraintView
+    
+    internal init(view: ConstraintView) {
+        self.view = view
+        
+    }
+    
+    internal var layoutConstraints: [LayoutConstraint] {
+        return self.layoutConstraintsHashTable.allObjects
+    }
+    
+    internal func add(layoutConstraints: [LayoutConstraint]) {
+        let hashTable = self.layoutConstraintsHashTable
+        for layoutConstraint in layoutConstraints {
+            hashTable.add(layoutConstraint)
+        }
+    }
+    
+    internal func remove(layoutConstraints: [LayoutConstraint]) {
+        let hashTable = self.layoutConstraintsHashTable
+        for layoutConstraint in layoutConstraints {
+            hashTable.remove(layoutConstraint)
+        }
+    }
+    
+    private var layoutConstraintsHashTable: NSHashTable<LayoutConstraint> {
+        let layoutConstraints: NSHashTable<LayoutConstraint>
+        
+        if let existing = objc_getAssociatedObject(self.view, &layoutConstraintsKey) as? NSHashTable<LayoutConstraint> {
+            layoutConstraints = existing
+        } else {
+            layoutConstraints = NSHashTable<LayoutConstraint>.weakObjects()
+            objc_setAssociatedObject(self.view, &layoutConstraintsKey, layoutConstraints, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+        return layoutConstraints
+        
+    }
+    
+}
+private var layoutConstraintsKey: UInt8 = 0

+ 78 - 117
Source/Debugging.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,75 +22,47 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to allow adding a snp_label to a View for debugging purposes
-*/
-public extension View {
-    
-    public var snp_label: String? {
-        get {
-            return objc_getAssociatedObject(self, &labelKey) as? String
-        }
-        set {
-            objc_setAssociatedObject(self, &labelKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
-        }
-    }
-    
-}
-
-/**
-    Used to allow adding a snp_label to a LayoutConstraint for debugging purposes
-*/
 public extension LayoutConstraint {
     
-    public var snp_label: String? {
-        get {
-            return objc_getAssociatedObject(self, &labelKey) as? String
-        }
-        set {
-            objc_setAssociatedObject(self, &labelKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_COPY_NONATOMIC)
-        }
-    }
-
     override public var description: String {
         var description = "<"
         
         description += descriptionForObject(self)
         
-        if let firstItem: AnyObject = self.firstItem {
+        if let firstItem = conditionalOptional(from: self.firstItem) {
             description += " \(descriptionForObject(firstItem))"
         }
         
-        if self.firstAttribute != .NotAnAttribute {
-            description += ".\(self.firstAttribute.snp_description)"
+        if self.firstAttribute != .notAnAttribute {
+            description += ".\(descriptionForAttribute(self.firstAttribute))"
         }
         
-        description += " \(self.relation.snp_description)"
+        description += " \(descriptionForRelation(self.relation))"
         
-        if let secondItem: AnyObject = self.secondItem {
+        if let secondItem = self.secondItem {
             description += " \(descriptionForObject(secondItem))"
         }
         
-        if self.secondAttribute != .NotAnAttribute {
-            description += ".\(self.secondAttribute.snp_description)"
+        if self.secondAttribute != .notAnAttribute {
+            description += ".\(descriptionForAttribute(self.secondAttribute))"
         }
         
         if self.multiplier != 1.0 {
             description += " * \(self.multiplier)"
         }
         
-        if self.secondAttribute == .NotAnAttribute {
+        if self.secondAttribute == .notAnAttribute {
             description += " \(self.constant)"
         } else {
             if self.constant > 0.0 {
                 description += " + \(self.constant)"
             } else if self.constant < 0.0 {
-                description += " - \(CGFloat.abs(self.constant))"
+                description += " - \(abs(self.constant))"
             }
         }
         
@@ -103,97 +75,86 @@ public extension LayoutConstraint {
         return description
     }
     
-    internal var snp_makerFile: String? {
-        return self.snp_constraint?.makerFile
-    }
-    
-    internal var snp_makerLine: UInt? {
-        return self.snp_constraint?.makerLine
+}
+
+private func descriptionForRelation(_ relation: NSLayoutRelation) -> String {
+    switch relation {
+    case .equal:                return "=="
+    case .greaterThanOrEqual:   return ">="
+    case .lessThanOrEqual:      return "<="
     }
-    
 }
 
-private var labelKey = ""
+private func descriptionForAttribute(_ attribute: NSLayoutAttribute) -> String {
+    #if os(iOS) || os(tvOS)
+        switch attribute {
+        case .notAnAttribute:       return "notAnAttribute"
+        case .top:                  return "top"
+        case .left:                 return "left"
+        case .bottom:               return "bottom"
+        case .right:                return "right"
+        case .leading:              return "leading"
+        case .trailing:             return "trailing"
+        case .width:                return "width"
+        case .height:               return "height"
+        case .centerX:              return "centerX"
+        case .centerY:              return "centerY"
+        case .lastBaseline:         return "lastBaseline"
+        case .firstBaseline:        return "firstBaseline"
+        case .topMargin:            return "topMargin"
+        case .leftMargin:           return "leftMargin"
+        case .bottomMargin:         return "bottomMargin"
+        case .rightMargin:          return "rightMargin"
+        case .leadingMargin:        return "leadingMargin"
+        case .trailingMargin:       return "trailingMargin"
+        case .centerXWithinMargins: return "centerXWithinMargins"
+        case .centerYWithinMargins: return "centerYWithinMargins"
+        }
+    #else
+        switch attribute {
+        case .notAnAttribute:       return "notAnAttribute"
+        case .top:                  return "top"
+        case .left:                 return "left"
+        case .bottom:               return "bottom"
+        case .right:                return "right"
+        case .leading:              return "leading"
+        case .trailing:             return "trailing"
+        case .width:                return "width"
+        case .height:               return "height"
+        case .centerX:              return "centerX"
+        case .centerY:              return "centerY"
+        case .lastBaseline:         return "lastBaseline"
+        case .firstBaseline:        return "firstBaseline"
+        }
+    #endif
+}
 
-private func descriptionForObject(object: AnyObject) -> String {
-    let pointerDescription = NSString(format: "%p", ObjectIdentifier(object).uintValue)
+private func conditionalOptional<T>(from object: Optional<T>) -> Optional<T> {
+    return object
+}
+
+private func conditionalOptional<T>(from object: T) -> Optional<T> {
+    return Optional.some(object)
+}
+
+private func descriptionForObject(_ object: AnyObject) -> String {
+    let pointerDescription = String(format: "%p", UInt(bitPattern: ObjectIdentifier(object)))
     var desc = ""
     
-    desc += object.dynamicType.description()
+    desc += type(of: object).description()
     
-    if let object = object as? View {
-        desc += ":\(object.snp_label ?? pointerDescription)"
+    if let object = object as? ConstraintView {
+        desc += ":\(object.snp.label ?? pointerDescription)"
     } else if let object = object as? LayoutConstraint {
-        desc += ":\(object.snp_label ?? pointerDescription)"
+        desc += ":\(object.label ?? pointerDescription)"
     } else {
         desc += ":\(pointerDescription)"
     }
     
-    if let object = object as? LayoutConstraint, let file = object.snp_makerFile, let line = object.snp_makerLine {
-        desc += "@\(file)#\(line)"
+    if let object = object as? LayoutConstraint, let file = object.constraint?.sourceLocation.0, let line = object.constraint?.sourceLocation.1 {
+        desc += "@\((file as NSString).lastPathComponent)#\(line)"
     }
     
     desc += ""
     return desc
 }
-
-private extension NSLayoutRelation {
-    
-    private var snp_description: String {
-        switch self {
-        case .Equal:                return "=="
-        case .GreaterThanOrEqual:   return ">="
-        case .LessThanOrEqual:      return "<="
-        }
-    }
-    
-}
-
-private extension NSLayoutAttribute {
-    
-    private var snp_description: String {
-        #if os(iOS) || os(tvOS)
-        switch self {
-        case .NotAnAttribute:       return "notAnAttribute"
-        case .Top:                  return "top"
-        case .Left:                 return "left"
-        case .Bottom:               return "bottom"
-        case .Right:                return "right"
-        case .Leading:              return "leading"
-        case .Trailing:             return "trailing"
-        case .Width:                return "width"
-        case .Height:               return "height"
-        case .CenterX:              return "centerX"
-        case .CenterY:              return "centerY"
-        case .LastBaseline:             return "baseline"
-        case .FirstBaseline:        return "firstBaseline"
-        case .TopMargin:            return "topMargin"
-        case .LeftMargin:           return "leftMargin"
-        case .BottomMargin:         return "bottomMargin"
-        case .RightMargin:          return "rightMargin"
-        case .LeadingMargin:        return "leadingMargin"
-        case .TrailingMargin:       return "trailingMargin"
-        case .CenterXWithinMargins: return "centerXWithinMargins"
-        case .CenterYWithinMargins: return "centerYWithinMargins"
-        }
-        #else
-        switch self {
-        case .NotAnAttribute:       return "notAnAttribute"
-        case .Top:                  return "top"
-        case .Left:                 return "left"
-        case .Bottom:               return "bottom"
-        case .Right:                return "right"
-        case .Leading:              return "leading"
-        case .Trailing:             return "trailing"
-        case .Width:                return "width"
-        case .Height:               return "height"
-        case .CenterX:              return "centerX"
-        case .CenterY:              return "centerY"
-        case .LastBaseline:             return "baseline"
-        default:                    return "default"
-        }
-        #endif
-        
-    }
-    
-}

+ 22 - 28
Source/LayoutConstraint.swift

@@ -1,7 +1,7 @@
 //
 //  SnapKit
 //
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
 //
 //  Permission is hereby granted, free of charge, to any person obtaining a copy
 //  of this software and associated documentation files (the "Software"), to deal
@@ -22,42 +22,36 @@
 //  THE SOFTWARE.
 
 #if os(iOS) || os(tvOS)
-import UIKit
+    import UIKit
 #else
-import AppKit
+    import AppKit
 #endif
 
-/**
-    Used to add extra information to the actual `NSLayoutConstraint`'s that will UIKit/AppKit will utilize
-*/
+
 public class LayoutConstraint: NSLayoutConstraint {
     
-    internal var snp_constraint: Constraint? = nil
+    public var label: String? {
+        get {
+            return self.identifier
+        }
+        set {
+            self.identifier = newValue
+        }
+    }
+    
+    internal var constraint: Constraint! = nil
     
 }
 
-internal func ==(left: LayoutConstraint, right: LayoutConstraint) -> Bool {
-    if left.firstItem !== right.firstItem {
-        return false
-    }
-    if left.secondItem !== right.secondItem {
-        return false
-    }
-    if left.firstAttribute != right.firstAttribute {
-        return false
-    }
-    if left.secondAttribute != right.secondAttribute {
-        return false
-    }
-    if left.relation != right.relation {
-        return false
-    }
-    if left.priority != right.priority {
-        return false
-    }
-    if left.multiplier != right.multiplier {
+internal func ==(lhs: LayoutConstraint, rhs: LayoutConstraint) -> Bool {
+    guard lhs.firstItem === rhs.firstItem &&
+          lhs.secondItem === rhs.secondItem &&
+          lhs.firstAttribute == rhs.firstAttribute &&
+          lhs.secondAttribute == rhs.secondAttribute &&
+          lhs.relation == rhs.relation &&
+          lhs.priority == rhs.priority &&
+          lhs.multiplier == rhs.multiplier else {
         return false
     }
     return true
 }
-

+ 36 - 0
Source/UILayoutGuide+Extensions.swift

@@ -0,0 +1,36 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#endif
+    
+    
+@available(iOS 9.0, *)
+public extension ConstraintLayoutGuide {
+    
+    public var snp: ConstraintLayoutGuideDSL {
+        return ConstraintLayoutGuideDSL(guide: self)
+    }
+    
+}

+ 36 - 0
Source/UILayoutSupport+Extensions.swift

@@ -0,0 +1,36 @@
+//
+//  SnapKit
+//
+//  Copyright (c) 2011-Present SnapKit Team - https://github.com/SnapKit
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+
+#if os(iOS) || os(tvOS)
+    import UIKit
+#endif
+
+    
+@available(iOS 8.0, *)
+public extension ConstraintLayoutSupport {
+    
+    public var snp: ConstraintLayoutSupportDSL {
+        return ConstraintLayoutSupportDSL(support: self)
+    }
+    
+}

+ 0 - 183
Source/View+SnapKit.swift

@@ -1,183 +0,0 @@
-//
-//  SnapKit
-//
-//  Copyright (c) 2011-2015 SnapKit Team - https://github.com/SnapKit
-//
-//  Permission is hereby granted, free of charge, to any person obtaining a copy
-//  of this software and associated documentation files (the "Software"), to deal
-//  in the Software without restriction, including without limitation the rights
-//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-//  copies of the Software, and to permit persons to whom the Software is
-//  furnished to do so, subject to the following conditions:
-//
-//  The above copyright notice and this permission notice shall be included in
-//  all copies or substantial portions of the Software.
-//
-//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-//  THE SOFTWARE.
-
-#if os(iOS) || os(tvOS)
-import UIKit
-public typealias View = UIView
-#else
-import AppKit
-public typealias View = NSView
-#endif
-
-/**
-    Used to expose public API on views
-*/
-public extension View {
-    
-    /// left edge
-    public var snp_left: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Left) }
-    
-    /// top edge
-    public var snp_top: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Top) }
-    
-    /// right edge
-    public var snp_right: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Right) }
-    
-    /// bottom edge
-    public var snp_bottom: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Bottom) }
-    
-    /// leading edge
-    public var snp_leading: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Leading) }
-    
-    /// trailing edge
-    public var snp_trailing: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Trailing) }
-    
-    /// width dimension
-    public var snp_width: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Width) }
-    
-    /// height dimension
-    public var snp_height: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Height) }
-    
-    /// centerX position
-    public var snp_centerX: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterX) }
-    
-    /// centerY position
-    public var snp_centerY: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterY) }
-    
-    /// baseline position
-    public var snp_baseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Baseline) }
-    
-    /// first baseline position
-    @available(iOS 8.0, *)
-    public var snp_firstBaseline: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.FirstBaseline) }
-    
-    /// left margin
-    @available(iOS 8.0, *)
-    public var snp_leftMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeftMargin) }
-    
-    /// right margin
-    @available(iOS 8.0, *)
-    public var snp_rightMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.RightMargin) }
-    
-    /// top margin
-    @available(iOS 8.0, *)
-    public var snp_topMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TopMargin) }
-    
-    /// bottom margin
-    @available(iOS 8.0, *)
-    public var snp_bottomMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.BottomMargin) }
-    
-    /// leading margin
-    @available(iOS 8.0, *)
-    public var snp_leadingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.LeadingMargin) }
-    
-    /// trailing margin
-    @available(iOS 8.0, *)
-    public var snp_trailingMargin: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.TrailingMargin) }
-    
-    /// centerX within margins
-    @available(iOS 8.0, *)
-    public var snp_centerXWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterXWithinMargins) }
-    
-    /// centerY within margins
-    @available(iOS 8.0, *)
-    public var snp_centerYWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterYWithinMargins) }
-    
-    // top + left + bottom + right edges
-    public var snp_edges: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Edges) }
-    
-    // width + height dimensions
-    public var snp_size: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Size) }
-    
-    // centerX + centerY positions
-    public var snp_center: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Center) }
-    
-    // top + left + bottom + right margins
-    @available(iOS 8.0, *)
-    public var snp_margins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.Margins) }
-    
-    // centerX + centerY within margins
-    @available(iOS 8.0, *)
-    public var snp_centerWithinMargins: ConstraintItem { return ConstraintItem(object: self, attributes: ConstraintAttributes.CenterWithinMargins) }
-    
-    /**
-        Prepares constraints with a `ConstraintMaker` and returns the made constraints but does not install them.
-
-        - parameter closure that will be passed the `ConstraintMaker` to make the constraints with
-        
-        - returns: the constraints made
-    */
-    public func snp_prepareConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> [Constraint] {
-        return ConstraintMaker.prepareConstraints(view: self, file: file, line: line, closure: closure)
-    }
-    
-    /**
-        Makes constraints with a `ConstraintMaker` and installs them along side any previous made constraints.
-        
-        - parameter closure that will be passed the `ConstraintMaker` to make the constraints with
-    */
-    public func snp_makeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void {
-        ConstraintMaker.makeConstraints(view: self, file: file, line: line, closure: closure)
-    }
-    
-    /**
-        Updates constraints with a `ConstraintMaker` that will replace existing constraints that match and install new ones.
-    
-        For constraints to match only the constant can be updated.
-    
-        - parameter closure that will be passed the `ConstraintMaker` to update the constraints with
-    */
-    public func snp_updateConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void {
-        ConstraintMaker.updateConstraints(view: self, file: file, line: line, closure: closure)
-    }
-    
-    /**
-        Remakes constraints with a `ConstraintMaker` that will first remove all previously made constraints and make and install new ones.
-    
-        - parameter closure that will be passed the `ConstraintMaker` to remake the constraints with
-    */
-    public func snp_remakeConstraints(file: String = #file, line: UInt = #line, @noescape closure: (make: ConstraintMaker) -> Void) -> Void {
-        ConstraintMaker.remakeConstraints(view: self, file: file, line: line, closure: closure)
-    }
-    
-    /**
-        Removes all previously made constraints.
-    */
-    public func snp_removeConstraints() {
-        ConstraintMaker.removeConstraints(view: self)
-    }
-    
-    internal var snp_installedLayoutConstraints: [LayoutConstraint] {
-        get {
-            if let constraints = objc_getAssociatedObject(self, &installedLayoutConstraintsKey) as? [LayoutConstraint] {
-                return constraints
-            }
-            return []
-        }
-        set {
-            objc_setAssociatedObject(self, &installedLayoutConstraintsKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
-        }
-    }
-}
-
-private var installedLayoutConstraintsKey = ""

+ 253 - 89
Tests/Tests.swift

@@ -13,7 +13,7 @@ extension View {
 #endif
 
 import XCTest
-import SnapKit
+@testable import SnapKit
 
 class SnapKitTests: XCTestCase {
     
@@ -29,43 +29,49 @@ class SnapKitTests: XCTestCase {
         super.tearDown()
     }
     
-    func testLayoutGuideConstraints() {
-        #if os(iOS) || os(tvOS)
-        let vc = UIViewController()
-        vc.view = UIView(frame: CGRectMake(0, 0, 300, 300))
+    func testMakeConstraints() {
+        let v1 = View()
+        let v2 = View()
+        self.container.addSubview(v1)
+        self.container.addSubview(v2)
         
-        vc.view.addSubview(self.container)
+        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")
         
-        self.container.snp_makeConstraints { (make) -> Void in
-            make.top.equalTo(vc.snp_topLayoutGuideBottom)
-            make.bottom.equalTo(vc.snp_bottomLayoutGuideTop)
+        v2.snp.makeConstraints { (make) -> Void in
+            make.edges.equalTo(v1)
+            return
         }
         
-        XCTAssertEqual(vc.view.snp_constraints.count, 6, "Should have 6 constraints installed")
-        #endif
+        XCTAssertEqual(self.container.snp_constraints.count, 6, "Should have 6 constraints installed")
+        
     }
     
-    func testMakeConstraints() {
+    func testMakeImpliedSuperviewConstraints() {
         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)
+        v1.snp.makeConstraints { (make) -> Void in
+            make.top.equalTo(50.0)
+            make.left.equalTo(50.0)
             return
         }
         
         XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints installed")
         
-        v2.snp_makeConstraints { (make) -> Void in
+        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() {
@@ -74,16 +80,16 @@ class SnapKitTests: XCTestCase {
         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)
+        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)
+        v1.snp.updateConstraints { (make) -> Void in
+            make.top.equalTo(v2.snp.top).offset(15)
             return
         }
         
@@ -91,21 +97,22 @@ class SnapKitTests: XCTestCase {
         
     }
     
+    
     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)
+        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
+        v1.snp.remakeConstraints { (make) -> Void in
             make.edges.equalTo(v2)
             return
         }
@@ -120,15 +127,15 @@ class SnapKitTests: XCTestCase {
         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)
+        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()
+        v1.snp.removeConstraints()
         
         XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
         
@@ -140,7 +147,7 @@ class SnapKitTests: XCTestCase {
         self.container.addSubview(v1)
         self.container.addSubview(v2)
         
-        let constraints = v1.snp_prepareConstraints { (make) -> Void in
+        let constraints = v1.snp.prepareConstraints { (make) -> Void in
             make.edges.equalTo(v2)
             return
         }
@@ -148,26 +155,26 @@ class SnapKitTests: XCTestCase {
         XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
         
         for constraint in constraints {
-            constraint.install()
+            constraint.activate()
         }
         
         XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed")
         
         for constraint in constraints {
-            constraint.uninstall()
+            constraint.deactivate()
         }
         
         XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
         
     }
     
-    func testReinstallConstraints() {
+    func testReactivateConstraints() {
         let v1 = View()
         let v2 = View()
         self.container.addSubview(v1)
         self.container.addSubview(v2)
         
-        let constraints = v1.snp_prepareConstraints { (make) -> Void in
+        let constraints = v1.snp.prepareConstraints { (make) -> Void in
             make.edges.equalTo(v2)
             return
         }
@@ -176,16 +183,16 @@ class SnapKitTests: XCTestCase {
         XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
         
         for constraint in constraints {
-            constraint.install()
+            constraint.activate()
         }
         
         XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints installed")
         
         for constraint in constraints {
-            constraint.install()
+            constraint.deactivate()
         }
         
-        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 0 constraints installed")
+        XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints installed")
     }
     
     func testActivateDeactivateConstraints() {
@@ -197,9 +204,9 @@ class SnapKitTests: XCTestCase {
         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
+        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
         }
         
@@ -215,11 +222,6 @@ class SnapKitTests: XCTestCase {
         
         XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints")
         
-        c1?.uninstall()
-        c2?.uninstall()
-        
-        XCTAssertEqual(self.container.snp_constraints.count, 0, "Should have 0 constraints")
-        
         c1?.activate()
         c2?.activate()
         
@@ -227,12 +229,127 @@ class SnapKitTests: XCTestCase {
         
     }
     
+    func testEdgeConstraints() {
+        let view = View()
+        self.container.addSubview(view)
+        
+        view.snp.makeConstraints { (make) -> Void in
+            make.edges.equalTo(self.container).offset(50.0)
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
+        
+        
+        let constraints = self.container.snp_constraints as! [NSLayoutConstraint]
+        
+        XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[2].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[3].constant, 50, "Should be 50")
+    }
+    
+    func testUpdateReferencedConstraints() {
+        let v1 = View()
+        let v2 = View()
+        self.container.addSubview(v1)
+        self.container.addSubview(v2)
+        
+        var c1: Constraint! = nil
+        var c2: Constraint! = nil
+        
+        v1.snp.makeConstraints { (make) -> Void in
+            c1 = make.top.equalTo(v2).offset(50).constraint
+            c2 = make.bottom.equalTo(v2).offset(25).constraint
+            return
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
+        
+        let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
+        
+        XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[1].constant, 25, "Should be 25")
+        
+        c1.update(offset: 15)
+        c2.update(offset: 20)
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
+        
+        XCTAssertEqual(constraints[0].constant, 15, "Should be 15")
+        XCTAssertEqual(constraints[1].constant, 20, "Should be 20")
+        
+        c1.update(inset: 15)
+        c2.update(inset: 20)
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
+        
+        XCTAssertEqual(constraints[0].constant, 15, "Should be 15")
+        XCTAssertEqual(constraints[1].constant, -20, "Should be -20")
+        
+    }
+    
+    func testInsetsAsConstraintsConstant() {
+        let view = View()
+        self.container.addSubview(view)
+        
+        view.snp.makeConstraints { (make) -> Void in
+            make.edges.equalTo(self.container).inset(50.0)
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
+        
+        let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
+        
+        XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[2].constant, -50, "Should be -50")
+        XCTAssertEqual(constraints[3].constant, -50, "Should be -50")
+    }
+    
+    func testConstraintInsetsAsImpliedEqualToConstraints() {
+        let view = View()
+        self.container.addSubview(view)
+        
+        view.snp.makeConstraints { (make) -> Void in
+            make.edges.equalTo(ConstraintInsets(top: 25, left: 25, bottom: 25, right: 25))
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
+        
+        
+        let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
+        
+        XCTAssertEqual(constraints[0].constant, 25, "Should be 25")
+        XCTAssertEqual(constraints[1].constant, 25, "Should be 25")
+        XCTAssertEqual(constraints[2].constant, -25, "Should be -25")
+        XCTAssertEqual(constraints[3].constant, -25, "Should be -25")
+    }
+    
+    func testConstraintInsetsAsConstraintsConstant() {
+        let view = View()
+        self.container.addSubview(view)
+        
+        view.snp.makeConstraints { (make) -> Void in
+            make.edges.equalTo(self.container).inset(ConstraintInsets(top: 25, left: 25, bottom: 25, right: 25))
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
+        
+        
+        let constraints = (self.container.snp_constraints as! [NSLayoutConstraint]).sorted { $0.constant > $1.constant }
+        
+        XCTAssertEqual(constraints[0].constant, 25, "Should be 25")
+        XCTAssertEqual(constraints[1].constant, 25, "Should be 25")
+        XCTAssertEqual(constraints[2].constant, -25, "Should be -25")
+        XCTAssertEqual(constraints[3].constant, -25, "Should be -25")
+    }
+    
     func testSizeConstraints() {
         let view = View()
         self.container.addSubview(view)
         
-        view.snp_makeConstraints { (make) -> Void in
-            make.size.equalTo(CGSizeMake(50, 50))
+        view.snp.makeConstraints { (make) -> Void in
+            make.size.equalTo(CGSize(width: 50, height: 50))
             make.left.top.equalTo(self.container)
         }
         
@@ -240,11 +357,32 @@ class SnapKitTests: XCTestCase {
         
         XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
         
-        
         let constraints = view.snp_constraints as! [NSLayoutConstraint]
+
+        // no guarantee which order the constraints are in, but we should test their couple
+        let widthHeight = (NSLayoutAttribute.width.rawValue, NSLayoutAttribute.height.rawValue)
+        let heightWidth = (widthHeight.1, widthHeight.0)
+        let firstSecond = (constraints[0].firstAttribute.rawValue, constraints[1].firstAttribute.rawValue)
+
+        // constraint values are correct in either width, height or height, width order
+        XCTAssertTrue(firstSecond == widthHeight || firstSecond == heightWidth, "2 contraint values should match")
+        XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
+        XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
+    }
+    
+    func testCenterConstraints() {
+        let view = View()
+        self.container.addSubview(view)
+        
+        view.snp.makeConstraints { (make) -> Void in
+            make.center.equalTo(self.container).offset(50.0)
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 2, "Should have 2 constraints")
+        
+        
+        let constraints = self.container.snp_constraints as! [NSLayoutConstraint]
         
-        XCTAssertEqual(constraints[0].firstAttribute, NSLayoutAttribute.Width, "Should be width")
-        XCTAssertEqual(constraints[1].firstAttribute, NSLayoutAttribute.Height, "Should be height")
         XCTAssertEqual(constraints[0].constant, 50, "Should be 50")
         XCTAssertEqual(constraints[1].constant, 50, "Should be 50")
     }
@@ -254,64 +392,90 @@ class SnapKitTests: XCTestCase {
         let view = View()
         self.container.addSubview(view)
         
-        view.snp_makeConstraints { (make) -> Void in
-            make.top.equalTo(self.container.snp_top).labeled(identifier)
+        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() {
+    #if os(iOS) || os(tvOS)
+    func testEdgesToMargins() {
+        var fromAttributes = Set<NSLayoutAttribute>()
+        var toAttributes = Set<NSLayoutAttribute>()
+        
         let view = View()
+        self.container.addSubview(view)
         
-        container.addSubview(view)
+        view.snp.remakeConstraints { (make) -> Void in
+            make.edges.equalTo(self.container.snp.margins)
+        }
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
         
-        view.snp_makeConstraints { (make) -> Void in
-            make.top.equalToSuperview().inset(10)
-            make.bottom.equalToSuperview().inset(10)
+        for constraint in (container.snp_constraints as! [NSLayoutConstraint]) {
+            fromAttributes.insert(constraint.firstAttribute)
+            toAttributes.insert(constraint.secondAttribute)
         }
         
-        XCTAssertEqual(container.snp_constraints.count, 2, "Should have 2 constraints")
+        XCTAssert(fromAttributes == [.top, .left, .bottom, .right])
+        XCTAssert(toAttributes == [.topMargin, .leftMargin, .bottomMargin, .rightMargin])
         
-        let constraints = container.snp_constraints as! [NSLayoutConstraint]
+        fromAttributes.removeAll()
+        toAttributes.removeAll()
         
-        XCTAssertEqual(constraints[0].firstAttribute, NSLayoutAttribute.Top, "Should be top")
-        XCTAssertEqual(constraints[1].firstAttribute, NSLayoutAttribute.Bottom, "Should be bottom")
+        view.snp.remakeConstraints { (make) -> Void in
+            make.margins.equalTo(self.container.snp.edges)
+        }
         
-        XCTAssertEqual(constraints[0].secondAttribute, NSLayoutAttribute.Top, "Should be top")
-        XCTAssertEqual(constraints[1].secondAttribute, NSLayoutAttribute.Bottom, "Should be bottom")
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
         
-        XCTAssertEqual(constraints[0].firstItem as? View, view, "Should be added subview")
-        XCTAssertEqual(constraints[1].firstItem as? View, view, "Should be added subview")
+        for constraint in (container.snp_constraints as! [NSLayoutConstraint]) {
+            fromAttributes.insert(constraint.firstAttribute)
+            toAttributes.insert(constraint.secondAttribute)
+        }
         
-        XCTAssertEqual(constraints[0].secondItem as? View, container, "Should be containerView")
-        XCTAssertEqual(constraints[1].secondItem as? View, container, "Should be containerView")
+        XCTAssert(toAttributes == [.top, .left, .bottom, .right])
+        XCTAssert(fromAttributes == [.topMargin, .leftMargin, .bottomMargin, .rightMargin])
         
-        XCTAssertEqual(constraints[0].constant, 10, "Should be 10")
-        XCTAssertEqual(constraints[1].constant, -10, "Should be 10")
     }
-
-    func testNativeConstraints() {
+    
+    func testEdgesToEdges() {
+        var fromAttributes = Set<NSLayoutAttribute>()
+        var toAttributes = Set<NSLayoutAttribute>()
+        
         let view = View()
+        self.container.addSubview(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
+        view.snp.remakeConstraints { (make) -> Void in
+            make.edges.equalTo(self.container.snp.edges)
         }
-
-        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")
+        
+        XCTAssertEqual(self.container.snp_constraints.count, 4, "Should have 4 constraints")
+        
+        for constraint in (container.snp_constraints as! [NSLayoutConstraint]) {
+            fromAttributes.insert(constraint.firstAttribute)
+            toAttributes.insert(constraint.secondAttribute)
+        }
+        
+        XCTAssert(fromAttributes == [.top, .left, .bottom, .right])
+        XCTAssert(toAttributes == [.top, .left, .bottom, .right])
+    }
+    
+    func testLayoutGuideConstraints() {
+        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.topLayoutGuide.snp.bottom)
+        make.bottom.equalTo(vc.bottomLayoutGuide.snp.top)
+        }
+         
+        XCTAssertEqual(vc.view.snp_constraints.count, 6, "Should have 6 constraints installed")
     }
+    #endif
+    
 }

Неке датотеке нису приказане због велике количине промена