From 7b3ea6eb3d6bc09d7ae8656788677cd2c7fe23f1 Mon Sep 17 00:00:00 2001 From: Satinder Singh Date: Tue, 6 Jun 2017 17:45:57 -0700 Subject: [PATCH] [FEATURE] Support Priority - SnapLayout now supports priority with all snaps! - Added test for priority - Updated Example project priority cell with update --- Example/Podfile.lock | 4 +- .../Local Podspecs/SnapLayout.podspec.json | 7 +- Example/Pods/Manifest.lock | 4 +- .../SnapLayout-OSX/Info.plist | 2 +- .../SnapLayout-iOS/Info.plist | 2 +- .../SnapLayout_ExampleTests.xcscheme | 3 +- .../AdjacentHorizontalTableViewCell.swift | 2 +- .../SnapLayout/Base.lproj/LaunchScreen.xib | 12 ++-- Example/SnapLayout/Info.plist | 2 + .../SnapLayout/PriorityTableViewCell.swift | 10 ++- Example/SnapLayout/ViewController.swift | 2 +- .../SnapLayoutTests.swift | 12 ++++ .../SnapManagerTests.swift | 6 +- README.md | 36 +++++++--- SnapLayout.podspec | 2 +- SnapLayout/Classes/Aliases.swift | 8 +++ SnapLayout/Classes/SnapLayout.swift | 70 ++++++++++++------- SnapLayout/Classes/SnapManager.swift | 43 +++++++----- 18 files changed, 147 insertions(+), 80 deletions(-) diff --git a/Example/Podfile.lock b/Example/Podfile.lock index c5bb407..84fbc2f 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - SnapLayout (1.6.2) + - SnapLayout (1.8.0) DEPENDENCIES: - SnapLayout (from `../`) @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - SnapLayout: 387502e5b6acbd2f12308fab94425907a87866c1 + SnapLayout: bef399cd9d9cf1959e249edd58eadc60836862dc PODFILE CHECKSUM: 15badb46d75d789f8e26d30c1acb2aa5249c4ced diff --git a/Example/Pods/Local Podspecs/SnapLayout.podspec.json b/Example/Pods/Local Podspecs/SnapLayout.podspec.json index 713d942..51d6592 100644 --- a/Example/Pods/Local Podspecs/SnapLayout.podspec.json +++ b/Example/Pods/Local Podspecs/SnapLayout.podspec.json @@ -1,6 +1,6 @@ { "name": "SnapLayout", - "version": "1.6.2", + "version": "1.8.0", "summary": "Concise API for iOS Auto Layout", "description": "# SnapLayout\nConcise API for iOS Auto Layout. SnapLayout extends `UIView` to deliver a list of APIs to improve\n readability while also shortening constraint code. Internally uses AutoLayout to provide the best \n experience. With SnapLayout, developers can remove boilerplate code but not at the cost of readability.\n\nImagine applying any or all of the following constraints in one line of code: top, leading, trailing, \nbottom, width, height, centerX, centerY. This is possible with `SnapLayout`.", "homepage": "https://github.com/sp71/SnapLayout", @@ -13,11 +13,12 @@ }, "source": { "git": "https://github.com/sp71/SnapLayout.git", - "tag": "1.6.2" + "tag": "1.8.0" }, "platforms": { "ios": "9.0", - "osx": "10.11" + "osx": "10.11", + "tvos": "9.0" }, "requires_arc": true, "source_files": "SnapLayout/Classes/**/*" diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock index c5bb407..84fbc2f 100644 --- a/Example/Pods/Manifest.lock +++ b/Example/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - SnapLayout (1.6.2) + - SnapLayout (1.8.0) DEPENDENCIES: - SnapLayout (from `../`) @@ -9,7 +9,7 @@ EXTERNAL SOURCES: :path: "../" SPEC CHECKSUMS: - SnapLayout: 387502e5b6acbd2f12308fab94425907a87866c1 + SnapLayout: bef399cd9d9cf1959e249edd58eadc60836862dc PODFILE CHECKSUM: 15badb46d75d789f8e26d30c1acb2aa5249c4ced diff --git a/Example/Pods/Target Support Files/SnapLayout-OSX/Info.plist b/Example/Pods/Target Support Files/SnapLayout-OSX/Info.plist index 1040bc4..7d91f91 100644 --- a/Example/Pods/Target Support Files/SnapLayout-OSX/Info.plist +++ b/Example/Pods/Target Support Files/SnapLayout-OSX/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.6.2 + 1.8.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/Pods/Target Support Files/SnapLayout-iOS/Info.plist b/Example/Pods/Target Support Files/SnapLayout-iOS/Info.plist index 1040bc4..7d91f91 100644 --- a/Example/Pods/Target Support Files/SnapLayout-iOS/Info.plist +++ b/Example/Pods/Target Support Files/SnapLayout-iOS/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.6.2 + 1.8.0 CFBundleSignature ???? CFBundleVersion diff --git a/Example/SnapLayout.xcodeproj/xcshareddata/xcschemes/SnapLayout_ExampleTests.xcscheme b/Example/SnapLayout.xcodeproj/xcshareddata/xcschemes/SnapLayout_ExampleTests.xcscheme index e3a5f1e..6c7c9b2 100644 --- a/Example/SnapLayout.xcodeproj/xcshareddata/xcschemes/SnapLayout_ExampleTests.xcscheme +++ b/Example/SnapLayout.xcodeproj/xcshareddata/xcschemes/SnapLayout_ExampleTests.xcscheme @@ -10,7 +10,8 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> diff --git a/Example/SnapLayout/AdjacentHorizontalTableViewCell.swift b/Example/SnapLayout/AdjacentHorizontalTableViewCell.swift index e811419..d4bd386 100644 --- a/Example/SnapLayout/AdjacentHorizontalTableViewCell.swift +++ b/Example/SnapLayout/AdjacentHorizontalTableViewCell.swift @@ -27,7 +27,7 @@ internal final class AdjacentHorizontalTableViewCell: TitleTableViewCell { fileprivate func setupLabels() { let leadingLabel = Style.subtitleLabel(text: "Leading Label") contentView.addSubview(leadingLabel) - leadingLabel.snap(constants: leadingLabelConfig) + leadingLabel.snap(config: leadingLabelConfig) let trailingLabel = Style.subtitleLabel(text: "Trailing Label") contentView.addSubview(trailingLabel) diff --git a/Example/SnapLayout/Base.lproj/LaunchScreen.xib b/Example/SnapLayout/Base.lproj/LaunchScreen.xib index 82123ee..f3564ec 100644 --- a/Example/SnapLayout/Base.lproj/LaunchScreen.xib +++ b/Example/SnapLayout/Base.lproj/LaunchScreen.xib @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -24,7 +28,7 @@ - + diff --git a/Example/SnapLayout/Info.plist b/Example/SnapLayout/Info.plist index fbe1e6b..22717db 100644 --- a/Example/SnapLayout/Info.plist +++ b/Example/SnapLayout/Info.plist @@ -20,5 +20,7 @@ $(CURRENT_PROJECT_VERSION) NSPrincipalClass + UILaunchStoryboardName + LaunchScreen diff --git a/Example/SnapLayout/PriorityTableViewCell.swift b/Example/SnapLayout/PriorityTableViewCell.swift index 6e7d845..3d2bf20 100644 --- a/Example/SnapLayout/PriorityTableViewCell.swift +++ b/Example/SnapLayout/PriorityTableViewCell.swift @@ -7,6 +7,7 @@ // import UIKit +import SnapLayout /// Displays rectangle view with a constraint whose priority is updated class PriorityTableViewCell: TitleTableViewCell { @@ -27,14 +28,11 @@ class PriorityTableViewCell: TitleTableViewCell { contentView.addSubview(rectangleView) // Snaps square view by pinning to all 4 sides (activated constraints) - // Then creates an inactive height constraint whose priority is updated before being activated through `squareViewSnapManager` + // Then creates a height constraint whose priority is updated and then activated // Updating height priority to avoid following runtime warning // http://stackoverflow.com/questions/28410309/strange-uiview-encapsulated-layout-height-error - let squareViewSnapManager = rectangleView - .snap(top: 48, leading: 16, bottom: 16, trailing: 16) - .snap(height: 40, isActive: false) - squareViewSnapManager.height?.priority = 999 - squareViewSnapManager.height?.isActive = true + rectangleView.snap(top: 48, leading: 16, bottom: 16, trailing: 16) + .snap(height: 40, priority: UILayoutPriorityDefaultHigh) let circleView = UIView() circleView.backgroundColor = .green diff --git a/Example/SnapLayout/ViewController.swift b/Example/SnapLayout/ViewController.swift index 56838b3..1041d56 100644 --- a/Example/SnapLayout/ViewController.swift +++ b/Example/SnapLayout/ViewController.swift @@ -38,7 +38,7 @@ internal final class ViewController: UIViewController { tableView.allowsSelection = false tableView.tableFooterView = UIView(frame: .zero) view.addSubview(tableView) - tableView.snap(constants: .zero) // snaps top, leading, bottom, and trailing + tableView.snap(config: .zero) // snaps top, leading, bottom, and trailing } } diff --git a/Example/SnapLayout_ExampleTests/SnapLayoutTests.swift b/Example/SnapLayout_ExampleTests/SnapLayoutTests.swift index 65968d6..60b1dcf 100644 --- a/Example/SnapLayout_ExampleTests/SnapLayoutTests.swift +++ b/Example/SnapLayout_ExampleTests/SnapLayoutTests.swift @@ -170,5 +170,17 @@ class SnapLayoutTests: BaseTestCase { XCTAssertEqual(snapManagerInActive.top!.constant, topConstant) XCTAssertEqual(snapManagerInActive.top!.multiplier, 1.0) } + + /// Tests priority for a snap + func testPriority() { + let snapManagerDefaultPriority = childView.snapHeight(to: childView2, multiplier: 0.5) + XCTAssertEqual(snapManagerDefaultPriority.height!.priority, LayoutPriorityRequired) + + let snapManagerHighPriority = childView.snapWidth(to: childView2, priority: UILayoutPriorityDefaultHigh) + XCTAssertEqual(snapManagerHighPriority.width!.priority, UILayoutPriorityDefaultHigh) + + let snapManagerLowPriority = childView.snap(top: 100, priority: UILayoutPriorityDefaultLow) + XCTAssertEqual(snapManagerLowPriority.top!.priority, UILayoutPriorityDefaultLow) + } } diff --git a/Example/SnapLayout_ExampleTests/SnapManagerTests.swift b/Example/SnapLayout_ExampleTests/SnapManagerTests.swift index c9495c5..13a7ecc 100644 --- a/Example/SnapLayout_ExampleTests/SnapManagerTests.swift +++ b/Example/SnapLayout_ExampleTests/SnapManagerTests.swift @@ -90,7 +90,7 @@ class SnapManagerTests: BaseTestCase { let containerView = UIView() containerView.addSubview(containerViewSubview) containerView.addSubview(otherView) - let snapManager = containerViewSubview.snap(to: otherView, constants: .zero) + let snapManager = containerViewSubview.snap(to: otherView, config: .zero) XCTAssertEqual(containerViewSubview.translatesAutoresizingMaskIntoConstraints, false) XCTAssertNotNil(snapManager.top) XCTAssertEqual(snapManager.top!.constant, 0) @@ -124,7 +124,7 @@ class SnapManagerTests: BaseTestCase { height: heightConstant, centerX: centerXConstant, centerY: centerYConstant) - let snapManager = childView.snap(constants: snapConfig) + let snapManager = childView.snap(config: snapConfig) XCTAssertEqual(childView.translatesAutoresizingMaskIntoConstraints, false) XCTAssertNotNil(snapManager.top) XCTAssertEqual(snapManager.top!.constant, topConstant) @@ -162,7 +162,7 @@ class SnapManagerTests: BaseTestCase { width: widthConstant, height: heightConstant) let centerConfig = SnapConfig(centerX: centerXConstant, centerY: centerYConstant) - let snapManager = childView.snap(constants: snapConfig) + let snapManager = childView.snap(config: snapConfig) .snap(config: centerConfig) XCTAssertNotNil(snapManager.top) XCTAssertEqual(snapManager.top!.constant, topConstant) diff --git a/README.md b/README.md index 2ef9737..6e8e051 100644 --- a/README.md +++ b/README.md @@ -69,15 +69,15 @@ github "sp71/SnapLayout" ### [`Methods`](SnapLayout/Classes/SnapLayout.swift) ```swift -func snap(to view: View? = nil, top: CGFloat? = nil, leading: CGFloat? = nil, bottom: CGFloat? = nil, trailing: CGFloat? = nil, width: CGFloat? = nil, height: CGFloat? = nil, centerX: CGFloat? = nil, centerY: CGFloat? = nil, isActive: Bool = true) -> SnapManager -func snap(to view: View? = nil, constants: SnapConfig, isActive: Bool = true) -> SnapManager -func snapWidth(to view: View, multiplier: CGFloat = 1, isActive: Bool = true) -> SnapManager -func snapHeight(to view: View, multiplier: CGFloat = 1, isActive: Bool = true) -> SnapManager -func snap(size: CGSize, isActive: Bool = true) -> SnapManager -func snap(trailingView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager -func snap(leadingView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager -func snap(bottomView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager -func snap(topView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager +func snap(to view: View? = nil, top: CGFloat? = nil, leading: CGFloat? = nil, bottom: CGFloat? = nil, trailing: CGFloat? = nil, width: CGFloat? = nil, height: CGFloat? = nil, centerX: CGFloat? = nil, centerY: CGFloat? = nil, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snap(to view: View? = nil, config: SnapConfig, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snapWidth(to view: View, multiplier: CGFloat = 1, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snapHeight(to view: View, multiplier: CGFloat = 1, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snap(size: CGSize, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snap(trailingView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snap(leadingView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snap(bottomView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager +func snap(topView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager ``` ### Sample Code @@ -102,12 +102,26 @@ print(snapManager.top?.constant) # 8.0 print(snapManager.height?.constant) # 0.5 ``` Snap calls may also be chained and will continue to return a `SnapManager`. -### Constants +### Config A `SnapConfig ` struct is also available where a developer may list all of their constraint constants beforehand and provide this type to the snap method argument. ```swift let config = SnapConfig(top: 50, leading: 50, trailing: 50, width: 30, centerX: 0) -button.snap(constants: config) +button.snap(config: config) +``` + +### Priority +SnapLayout assumes required priority (same default as Apple) unless otherwise specified for those created constraints. + +```swift +button1.snap(trailingView: button2, constant: 8, priority: UILayoutPriorityDefaultLow) +``` + +In the following example, the top, leading, bottom, and trailing constraint all have a priority of required; however, the height constraint has a `UILayoutPriorityDefaultHigh` priority. That's it! + +```swift +rectangleView.snap(top: 48, leading: 16, bottom: 16, trailing: 16) + .snap(height: 40, priority: UILayoutPriorityDefaultHigh) ``` ### To Activate or not to Activate diff --git a/SnapLayout.podspec b/SnapLayout.podspec index 18a503e..496d366 100644 --- a/SnapLayout.podspec +++ b/SnapLayout.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| s.name = 'SnapLayout' - s.version = '1.7.0' + s.version = '1.8.0' s.summary = 'Concise API for iOS Auto Layout' s.description = <<-DESC diff --git a/SnapLayout/Classes/Aliases.swift b/SnapLayout/Classes/Aliases.swift index d7300a0..572c45e 100644 --- a/SnapLayout/Classes/Aliases.swift +++ b/SnapLayout/Classes/Aliases.swift @@ -9,7 +9,15 @@ #if os(iOS) || os(tvOS) /// Allows views to be OS independent while leveraging existing code public typealias View = UIView + /// Allows layout priority to be OS independent while leveraging existing code + public typealias LayoutPriority = UILayoutPriority + /// Allows layout priority required to be OS independent while leveraging existing code + public var LayoutPriorityRequired = UILayoutPriorityRequired #elseif os(OSX) /// Allows views to be OS independent while leveraging existing code public typealias View = NSView + /// Allows layout priority to be OS independent while leveraging existing code + public typealias LayoutPriority = NSLayoutPriority + /// Allows layout priority required to be OS independent while leveraging existing code + public var LayoutPriorityRequired = NSLayoutPriorityRequired #endif diff --git a/SnapLayout/Classes/SnapLayout.swift b/SnapLayout/Classes/SnapLayout.swift index fb9b45c..3dead88 100644 --- a/SnapLayout/Classes/SnapLayout.swift +++ b/SnapLayout/Classes/SnapLayout.swift @@ -12,7 +12,6 @@ public extension View { /// Snap to view based on argument values. /// - Warning: Since all parameters have default values, it is possible to call `snap()` with no parameters. /// This is **strongly** discouraged. - /// /// - Parameters: /// - view: View to to apply constraints with (defaulted to superview if nil) /// - top: Constant to apply to top constraint from topAnchor (if nil, not applied) @@ -23,22 +22,23 @@ public extension View { /// - height: Constant to apply from heightAnchor (if nil, not applied) /// - centerX: Constant offset to apply from centerXAnchor (if nil, not applied) /// - centerY: Constant offset to apply from centerXAnchor (if nil, not applied) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) - /// - Note: width and height are not in respect to superview, but always to self + /// - Note: width and height are not in respect to superview, but always to self. /// - Returns: SnapManager holding all the values associated with constraints @discardableResult func snap(to view: View? = nil, top: CGFloat? = nil, leading: CGFloat? = nil, bottom: CGFloat? = nil, trailing: CGFloat? = nil, width: CGFloat? = nil, height: CGFloat? = nil, centerX: CGFloat? = nil, - centerY: CGFloat? = nil, isActive: Bool = true) -> SnapManager { + centerY: CGFloat? = nil, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false var snapManager = SnapManager(view: self) var constraintList = [NSLayoutConstraint]() defer { - if isActive { + constraintList.forEach { $0.priority = priority } + if constraintList.count == 0 { + Swift.print("SnapLayout Error - No constraint was applied for view: \(String(describing: view))") + } else if isActive { NSLayoutConstraint.activate(constraintList) - if constraintList.count == 0 { - Swift.print("SnapLayout Error - No constraint was applied for view: \(String(describing: view))") - } } } if let width = width { @@ -92,20 +92,22 @@ public extension View { /// /// - Parameters: /// - view: View to to apply constraints with (defaulted to superview if nil) - /// - constants: ConstraintConstants to apply + /// - config: SnapConfig to apply + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snap(to view: View? = nil, constants: SnapConfig, isActive: Bool = true) -> SnapManager { + func snap(to view: View? = nil, config: SnapConfig, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { return snap(to: view, - top: constants.top, - leading: constants.leading, - bottom: constants.bottom, - trailing: constants.trailing, - width: constants.width, - height: constants.height, - centerX: constants.centerX, - centerY: constants.centerY, + top: config.top, + leading: config.leading, + bottom: config.bottom, + trailing: config.trailing, + width: config.width, + height: config.height, + centerX: config.centerX, + centerY: config.centerY, + priority: priority, isActive: isActive) } @@ -114,13 +116,15 @@ public extension View { /// - Parameters: /// - view: View to apply constraint with (defaulted to superview if nil) /// - multiplier: Multiplier value to apply constraint with (default 1) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snapWidth(to view: View, multiplier: CGFloat = 1, isActive: Bool = true) -> SnapManager { + func snapWidth(to view: View, multiplier: CGFloat = 1, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false let snapManager = SnapManager(view: self) snapManager.width = widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: multiplier) + snapManager.width?.priority = priority snapManager.width?.isActive = isActive return snapManager } @@ -130,25 +134,29 @@ public extension View { /// - Parameters: /// - view: View to apply constraint with (defaulted to superview if nil) /// - multiplier: Multiplier value to apply constraint with (default 1) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snapHeight(to view: View, multiplier: CGFloat = 1, isActive: Bool = true) -> SnapManager { + func snapHeight(to view: View, multiplier: CGFloat = 1, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false let snapManager = SnapManager(view: self) snapManager.height = heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: multiplier) + snapManager.height?.priority = priority snapManager.height?.isActive = isActive return snapManager } /// Anchor size by applying width anchor and height anchor /// - /// - Parameter size: CGSize specifying width and height - /// - isActive: Boolean determining if constraint should be activated (default true) + /// - Parameters: + /// - size: CGSize specifying width and height + /// - isActive: Boolean determining if constraint should be activated (default true) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snap(size: CGSize, isActive: Bool = true) -> SnapManager { - return snap(width: size.width, height: size.height, isActive: isActive) + func snap(size: CGSize, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { + return snap(width: size.width, height: size.height, priority: priority, isActive: isActive) } /// Applies necessary constraint to ensure calling view will be leading view and the trailingView is on the trailing side. @@ -156,13 +164,15 @@ public extension View { /// - Parameters: /// - trailingView: View who will be shown as the trailingView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snap(trailingView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + func snap(trailingView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false let snapManager = SnapManager(view: self) snapManager.trailing = trailingView.leadingAnchor.constraint(equalTo: trailingAnchor, constant: constant) + snapManager.trailing?.priority = priority snapManager.trailing?.isActive = isActive return snapManager } @@ -172,13 +182,15 @@ public extension View { /// - Parameters: /// - leadingView: View who will be shown as the leadingView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snap(leadingView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + func snap(leadingView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false let snapManager = SnapManager(view: self) snapManager.leading = leadingAnchor.constraint(equalTo: leadingView.trailingAnchor, constant: constant) + snapManager.leading?.priority = priority snapManager.leading?.isActive = isActive return snapManager } @@ -188,13 +200,15 @@ public extension View { /// - Parameters: /// - bottomView: View who will be shown as the bottomView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snap(bottomView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + func snap(bottomView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false let snapManager = SnapManager(view: self) snapManager.bottom = bottomView.topAnchor.constraint(equalTo: bottomAnchor, constant: constant) + snapManager.bottom?.priority = priority snapManager.bottom?.isActive = isActive return snapManager } @@ -204,13 +218,15 @@ public extension View { /// - Parameters: /// - topView: View who will be shown as the bottomView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - func snap(topView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + func snap(topView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { translatesAutoresizingMaskIntoConstraints = false let snapManager = SnapManager(view: self) snapManager.top = topAnchor.constraint(equalTo: topView.bottomAnchor, constant: constant) + snapManager.top?.priority = priority snapManager.top?.isActive = isActive return snapManager } diff --git a/SnapLayout/Classes/SnapManager.swift b/SnapLayout/Classes/SnapManager.swift index eca197b..71e6ee9 100644 --- a/SnapLayout/Classes/SnapManager.swift +++ b/SnapLayout/Classes/SnapManager.swift @@ -58,13 +58,14 @@ public class SnapManager { /// - height: Constant to apply from heightAnchor (if nil, not applied) /// - centerX: Boolean determining if centerX should be applied (if nil, not applied) /// - centerY: Boolean determining if centerY should be applied (if nil, not applied) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Note: width and height are not in respect to superview, but always to self. /// - Returns: SnapManager holding all the values associated with constraints @discardableResult public func snap(to view: View? = nil, top: CGFloat? = nil, leading: CGFloat? = nil, bottom: CGFloat? = nil, trailing: CGFloat? = nil, width: CGFloat? = nil, height: CGFloat? = nil, centerX: CGFloat? = nil, - centerY: CGFloat? = nil, isActive: Bool = true) -> SnapManager { + centerY: CGFloat? = nil, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() @@ -78,6 +79,7 @@ public class SnapManager { height: height, centerX: centerX, centerY: centerY, + priority: priority, isActive: isActive) sync(with: newSnapManager) return self @@ -89,10 +91,11 @@ public class SnapManager { /// - Parameters: /// - view: View to to apply constraints with (defaulted to superview if nil) /// - config: SnapConfig to apply + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snap(to view: View? = nil, config: SnapConfig, isActive: Bool = true) -> SnapManager { + public func snap(to view: View? = nil, config: SnapConfig, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { return snap(to: view, top: config.top, leading: config.leading, @@ -102,6 +105,7 @@ public class SnapManager { height: config.height, centerX: config.centerX, centerY: config.centerY, + priority: priority, isActive: isActive) } @@ -110,15 +114,16 @@ public class SnapManager { /// - Parameters: /// - view: View to apply constraint with (defaulted to superview if nil) /// - multiplier: Multiplier value to apply constraint with (default 1) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snapWidth(to view: View, multiplier: CGFloat = 1, isActive: Bool = true) -> SnapManager { + public func snapWidth(to view: View, multiplier: CGFloat = 1, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snapWidth(to: view, multiplier: multiplier, isActive: isActive) + let newSnapManager = weakView.snapWidth(to: view, multiplier: multiplier, priority: priority, isActive: isActive) sync(with: newSnapManager) return self } @@ -128,15 +133,16 @@ public class SnapManager { /// - Parameters: /// - view: View to apply constraint with (defaulted to superview if nil) /// - multiplier: Multiplier value to apply constraint with (default 1) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snapHeight(to view: View, multiplier: CGFloat = 1, isActive: Bool = true) -> SnapManager { + public func snapHeight(to view: View, multiplier: CGFloat = 1, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snapHeight(to: view, multiplier: multiplier, isActive: isActive) + let newSnapManager = weakView.snapHeight(to: view, multiplier: multiplier, priority: priority, isActive: isActive) sync(with: newSnapManager) return self } @@ -145,14 +151,15 @@ public class SnapManager { /// /// - Parameter size: CGSize specifying width and height /// - Parameter isActive: Boolean determining if constraint should be activated (default true) + /// - Parameter priority: LayoutPriority to apply upon constraint (default required) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snap(size: CGSize, isActive: Bool = true) -> SnapManager { + public func snap(size: CGSize, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snap(size: size, isActive: isActive) + let newSnapManager = weakView.snap(size: size, priority: priority, isActive: isActive) sync(with: newSnapManager) return self } @@ -162,15 +169,16 @@ public class SnapManager { /// - Parameters: /// - trailingView: View who will be shown as the trailingView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snap(trailingView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + public func snap(trailingView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snap(trailingView: trailingView, constant: constant, isActive: isActive) + let newSnapManager = weakView.snap(trailingView: trailingView, constant: constant, priority: priority, isActive: isActive) sync(with: newSnapManager) return self } @@ -180,15 +188,16 @@ public class SnapManager { /// - Parameters: /// - leadingView: View who will be shown as the leadingView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snap(leadingView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + public func snap(leadingView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snap(leadingView: leadingView, constant: constant, isActive: isActive) + let newSnapManager = weakView.snap(leadingView: leadingView, constant: constant, priority: priority, isActive: isActive) sync(with: newSnapManager) return self } @@ -198,15 +207,16 @@ public class SnapManager { /// - Parameters: /// - bottomView: View who will be shown as the bottomView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snap(bottomView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + public func snap(bottomView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snap(bottomView: bottomView, constant: constant, isActive: isActive) + let newSnapManager = weakView.snap(bottomView: bottomView, constant: constant, priority: priority, isActive: isActive) sync(with: newSnapManager) return self } @@ -216,15 +226,16 @@ public class SnapManager { /// - Parameters: /// - topView: View who will be shown as the bottomView /// - constant: Constant value to apply constraint with (default 0) + /// - priority: LayoutPriority to apply upon constraint (default required) /// - isActive: Boolean determining if constraint should be activated (default true) /// - Returns: SnapManager holding all the values associated with constraints @discardableResult - public func snap(topView: View, constant: CGFloat = 0, isActive: Bool = true) -> SnapManager { + public func snap(topView: View, constant: CGFloat = 0, priority: LayoutPriority = LayoutPriorityRequired, isActive: Bool = true) -> SnapManager { guard let weakView = weakView else { print("SnapLayout Error - Cannot apply constraint upon a view that is not retained") return SnapManager() } - let newSnapManager = weakView.snap(topView: topView, constant: constant, isActive: isActive) + let newSnapManager = weakView.snap(topView: topView, constant: constant, priority: priority, isActive: isActive) sync(with: newSnapManager) return self }