From 6330843a42081db94449790d3786dabe811a30a3 Mon Sep 17 00:00:00 2001 From: Aleksandr Gusev Date: Thu, 7 Dec 2017 17:21:29 -0500 Subject: [PATCH] Support nested batches (without combining their constraints) --- AnchorageTests/AnchorageTests.swift | 45 +++++++++++++++++++++++++++++ Source/Anchorage.swift | 10 ++----- Source/Internal.swift | 8 ++--- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/AnchorageTests/AnchorageTests.swift b/AnchorageTests/AnchorageTests.swift index fd47497..5781ca3 100644 --- a/AnchorageTests/AnchorageTests.swift +++ b/AnchorageTests/AnchorageTests.swift @@ -588,6 +588,51 @@ class AnchorageTests: XCTestCase { XCTAssertEqual(height.firstAttribute, .height) XCTAssertEqual(height.secondAttribute, .height) } + + func testNestedBatchConstraints() { + var nestedConstraints: [NSLayoutConstraint] = [] + let constraints = Anchorage.batch { + view1.widthAnchor == view2.widthAnchor + nestedConstraints = Anchorage.batch(active: false) { + view1.heightAnchor == view2.heightAnchor / 2 ~ .low + } + view1.leadingAnchor == view2.leadingAnchor + } + + let width = constraints[0] + let leading = constraints[1] + let height = nestedConstraints[0] + + assertIdentical(width.firstItem, view1) + assertIdentical(width.secondItem, view2) + XCTAssertEqual(width.constant, 0, accuracy: cgEpsilon) + XCTAssertEqual(width.multiplier, 1, accuracy: cgEpsilon) + XCTAssertEqual(width.priority.rawValue, TestPriorityRequired.rawValue, accuracy: fEpsilon) + XCTAssertTrue(width.isActive) + XCTAssertEqual(width.relation, .equal) + XCTAssertEqual(width.firstAttribute, .width) + XCTAssertEqual(width.secondAttribute, .width) + + assertIdentical(height.firstItem, view1) + assertIdentical(height.secondItem, view2) + XCTAssertEqual(height.constant, 0, accuracy: cgEpsilon) + XCTAssertEqual(height.multiplier, 0.5, accuracy: cgEpsilon) + XCTAssertEqual(height.priority.rawValue, TestPriorityLow.rawValue, accuracy: fEpsilon) + XCTAssertFalse(height.isActive) + XCTAssertEqual(height.relation, .equal) + XCTAssertEqual(height.firstAttribute, .height) + XCTAssertEqual(height.secondAttribute, .height) + + assertIdentical(leading.firstItem, view1) + assertIdentical(leading.secondItem, view2) + XCTAssertEqual(leading.constant, 0, accuracy: cgEpsilon) + XCTAssertEqual(leading.multiplier, 1, accuracy: cgEpsilon) + XCTAssertEqual(leading.priority.rawValue, TestPriorityRequired.rawValue, accuracy: fEpsilon) + XCTAssertTrue(leading.isActive) + XCTAssertEqual(leading.relation, .equal) + XCTAssertEqual(leading.firstAttribute, .leading) + XCTAssertEqual(leading.secondAttribute, .leading) + } } diff --git a/Source/Anchorage.swift b/Source/Anchorage.swift index 80a47b3..afa1358 100644 --- a/Source/Anchorage.swift +++ b/Source/Anchorage.swift @@ -397,7 +397,6 @@ infix operator ~: PriorityPrecedence /// Any Anchorage constraints created inside the passed closure are returned in the array. /// -/// - Precondition: Can't be called inside or simultaneously with another batch. Batches cannot be nested. /// - Parameter closure: A closure that runs some Anchorage expressions. /// - Returns: An array of new, active `NSLayoutConstraint`s. @discardableResult public func batch(_ closure: () -> Void) -> [NSLayoutConstraint] { @@ -406,19 +405,16 @@ infix operator ~: PriorityPrecedence /// Any Anchorage constraints created inside the passed closure are returned in the array. /// -/// - Precondition: Can't be called inside or simultaneously with another batch. Batches cannot be nested. /// - Parameter active: Whether the created constraints should be active when they are returned. /// - Parameter closure: A closure that runs some Anchorage expressions. /// - Returns: An array of new `NSLayoutConstraint`s. public func batch(active: Bool, closure: () -> Void) -> [NSLayoutConstraint] { - precondition(currentBatch == nil) + let batch = ConstraintBatch() + batches.append(batch) defer { - currentBatch = nil + batches.removeLast() } - let batch = ConstraintBatch() - currentBatch = batch - closure() if active { diff --git a/Source/Internal.swift b/Source/Internal.swift index 0a9ab4f..fc222a2 100644 --- a/Source/Internal.swift +++ b/Source/Internal.swift @@ -312,7 +312,7 @@ internal struct ConstraintBuilder { // MARK: - Batching -internal var currentBatch: ConstraintBatch? +internal var batches: [ConstraintBatch] = [] internal class ConstraintBatch { @@ -333,7 +333,7 @@ internal class ConstraintBatch { /// /// - Parameter closure: The work to perform inside of a batch internal func performInBatch(closure: () -> Void) { - if currentBatch == nil { + if batches.isEmpty { batch(closure) } else { @@ -351,8 +351,8 @@ internal func finalize(constraint: NSLayoutConstraint, withPriority priority: Pr constraint.priority = priority.value - if let currentBatch = currentBatch { - currentBatch.add(constraint: constraint) + if let lastBatch = batches.last { + lastBatch.add(constraint: constraint) } else { constraint.isActive = true