From 495ff8cf51e75506ff6967547b458a35d7856a70 Mon Sep 17 00:00:00 2001 From: kean Date: Fri, 13 Sep 2024 19:16:03 -0400 Subject: [PATCH] Update for Swift 6 --- Align.xcodeproj/project.pbxproj | 43 ++++++++++++----- .../xcshareddata/xcschemes/Align.xcscheme | 2 +- Package.swift | 6 +-- Sources/Align.swift | 47 +++++++++---------- Tests/AnchorAPIsTests.swift | 6 +-- Tests/AnchorAlignmentTests.swift | 6 +-- Tests/AnchorCenterTests.swift | 6 +-- Tests/AnchorCollectionCenterTests.swift | 7 ++- Tests/AnchorCollectionEdgesTests.swift | 6 +-- Tests/AnchorCollectionSizeTests.swift | 6 +-- Tests/AnchorDimensionTests.swift | 6 +-- Tests/AnchorEdgeTests.swift | 8 ++-- Tests/AnchorPerformanceTests.swift | 5 ++ Tests/AnchorTests.swift | 6 +-- Tests/ConstraintsTests.swift | 19 ++++---- Tests/Extensions/Align+Extensions.swift | 6 +-- Tests/Extensions/XCTestExtensions.swift | 30 ++++++++++-- 17 files changed, 131 insertions(+), 84 deletions(-) diff --git a/Align.xcodeproj/project.pbxproj b/Align.xcodeproj/project.pbxproj index 02238c2..d7d3855 100644 --- a/Align.xcodeproj/project.pbxproj +++ b/Align.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -207,8 +207,9 @@ 0CE3610F1C86077B00EA70CF /* Project object */ = { isa = PBXProject; attributes = { + BuildIndependentTargetsInParallel = YES; LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1600; ORGANIZATIONNAME = "Alexander Grebenyuk"; TargetAttributes = { 0CC3A0661D7476A700754E59 = { @@ -305,7 +306,11 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_SUSPICIOUS_MOVES = YES; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "com.github.kean.Align-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; @@ -316,7 +321,11 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_WARN_SUSPICIOUS_MOVES = YES; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); PRODUCT_BUNDLE_IDENTIFIER = "com.github.kean.Align-iOS-Tests"; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -335,13 +344,14 @@ "$(inherited)", ); GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MACOSX_DEPLOYMENT_TARGET = 10.13; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + MACOSX_DEPLOYMENT_TARGET = 11.5; ONLY_ACTIVE_ARCH = YES; SUPPORTED_PLATFORMS = "iphoneos appletvos iphonesimulator appletvsimulator macosx"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_STRICT_CONCURRENCY = complete; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -355,12 +365,13 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; - MACOSX_DEPLOYMENT_TARGET = 10.13; + IPHONEOS_DEPLOYMENT_TARGET = 15.6; + MACOSX_DEPLOYMENT_TARGET = 11.5; SUPPORTED_PLATFORMS = "iphoneos appletvos iphonesimulator appletvsimulator macosx"; SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_STRICT_CONCURRENCY = complete; SWIFT_VERSION = 5.0; - TVOS_DEPLOYMENT_TARGET = 12.0; + TVOS_DEPLOYMENT_TARGET = 15.6; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -376,7 +387,11 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MARKETING_VERSION = 3.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.github.kean.Align; PRODUCT_NAME = Align; @@ -393,7 +408,11 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MARKETING_VERSION = 3.2.0; PRODUCT_BUNDLE_IDENTIFIER = com.github.kean.Align; PRODUCT_NAME = Align; diff --git a/Align.xcodeproj/xcshareddata/xcschemes/Align.xcscheme b/Align.xcodeproj/xcshareddata/xcschemes/Align.xcscheme index d979f33..77203df 100644 --- a/Align.xcodeproj/xcshareddata/xcschemes/Align.xcscheme +++ b/Align.xcodeproj/xcshareddata/xcschemes/Align.xcscheme @@ -1,6 +1,6 @@ { +@MainActor public struct LayoutAnchors { /// The underlying item. public let item: T @@ -104,7 +104,7 @@ public enum AnchorType { /// /// - tip: `UIView` does not provide anchor properties for the layout margin attributes. /// Instead, call `view.layoutMarginsGuide.anchors`. -public struct Anchor { // type and axis are phantom types +@MainActor public struct Anchor { // type and axis are phantom types let item: LayoutItem let attribute: NSLayoutConstraint.Attribute let offset: CGFloat @@ -130,23 +130,23 @@ public struct Anchor { // type and axis are phantom types } /// Returns a new anchor offset by a given amount. -public func + (anchor: Anchor, offset: CGFloat) -> Anchor { +@MainActor public func + (anchor: Anchor, offset: CGFloat) -> Anchor { anchor.offsetting(by: offset) } /// Returns a new anchor offset by a given amount. -public func - (anchor: Anchor, offset: CGFloat) -> Anchor { +@MainActor public func - (anchor: Anchor, offset: CGFloat) -> Anchor { anchor.offsetting(by: -offset) } /// Returns a new anchor with an constant multiplied by the given amount. -public func * (anchor: Anchor, multiplier: CGFloat) -> Anchor { +@MainActor public func * (anchor: Anchor, multiplier: CGFloat) -> Anchor { anchor.multiplied(by: multiplier) } // MARK: - Anchors (AnchorType.Alignment) -public extension Anchor where Type: AnchorType.Alignment { +@MainActor public extension Anchor where Type: AnchorType.Alignment { @discardableResult func equal(_ anchor: Anchor, constant: CGFloat = 0) -> NSLayoutConstraint { Constraints.add(self, anchor, constant: constant, relation: .equal) } @@ -162,7 +162,7 @@ public extension Anchor where Type: AnchorType.Alignment { // MARK: - Anchors (AnchorType.Dimension) -public extension Anchor where Type: AnchorType.Dimension { +@MainActor public extension Anchor where Type: AnchorType.Dimension { @discardableResult func equal(_ anchor: Anchor, constant: CGFloat = 0) -> NSLayoutConstraint { Constraints.add(self, anchor, constant: constant, relation: .equal) } @@ -178,7 +178,7 @@ public extension Anchor where Type: AnchorType.Dimension { // MARK: - Anchors (AnchorType.Dimension) -public extension Anchor where Type: AnchorType.Dimension { +@MainActor public extension Anchor where Type: AnchorType.Dimension { @discardableResult func equal(_ constant: CGFloat) -> NSLayoutConstraint { Constraints.add(item: item, attribute: attribute, relatedBy: .equal, constant: constant) } @@ -199,7 +199,7 @@ public extension Anchor where Type: AnchorType.Dimension { // MARK: - Anchors (AnchorType.Edge) -public extension Anchor where Type: AnchorType.Edge { +@MainActor public extension Anchor where Type: AnchorType.Edge { /// Pins the edge to the respected edges of the given container. @discardableResult func pin(to container: LayoutItem? = nil, inset: CGFloat = 0) -> NSLayoutConstraint { let isInverted = [.trailing, .right, .bottom].contains(attribute) @@ -217,7 +217,7 @@ public extension Anchor where Type: AnchorType.Edge { // MARK: - Anchors (AnchorType.Center) -public extension Anchor where Type: AnchorType.Center { +@MainActor public extension Anchor where Type: AnchorType.Center { /// Aligns the axis with a superview axis. @discardableResult func align(offset: CGFloat = 0) -> NSLayoutConstraint { Constraints.add(self, toItem: item.superview!, attribute: attribute, constant: offset) @@ -227,7 +227,7 @@ public extension Anchor where Type: AnchorType.Center { // MARK: - AnchorCollectionEdges /// Create multiple constraints at once by operating more than one edge at once. -public struct AnchorCollectionEdges { +@MainActor public struct AnchorCollectionEdges { let item: LayoutItem var isAbsolute = false @@ -317,10 +317,10 @@ public struct AnchorCollectionEdges { return constraints } - public struct Alignment { + public struct Alignment: Sendable { /// The alignment along the horizontal axis. - public enum Horizontal { + public enum Horizontal: Sendable { /// Pin both leading and trailing edges to the superview. case fill /// Center the view in the container along the vertical axis. @@ -336,7 +336,7 @@ public struct AnchorCollectionEdges { } /// The alignment along the vertical axis. - public enum Vertical { + public enum Vertical: Sendable { /// Pin both top and bottom edges to the superview. case fill /// Center the view in the container along the vertical axis. @@ -404,7 +404,7 @@ public struct AnchorCollectionEdges { // MARK: - AnchorCollectionCenter /// Create multiple constraints at once by using both `centerX` and `centerY` anchors. -public struct AnchorCollectionCenter { +@MainActor public struct AnchorCollectionCenter { let x: Anchor let y: Anchor @@ -438,7 +438,7 @@ public struct AnchorCollectionCenter { // MARK: - AnchorCollectionSize /// Create multiple constraints at once by using both `width` and `height` anchors. -public struct AnchorCollectionSize { +@MainActor public struct AnchorCollectionSize { let width: Anchor let height: Anchor @@ -504,16 +504,16 @@ public struct AnchorCollectionSize { /// // Create your constraints here /// } /// ``` -public final class Constraints: Collection { +@MainActor public final class Constraints: Collection { public typealias Element = NSLayoutConstraint public typealias Index = Int - public subscript(position: Int) -> NSLayoutConstraint { - get { constraints[position] } + public nonisolated subscript(position: Int) -> NSLayoutConstraint { + get { MainActor.assumeIsolated { constraints[position] } } } - public var startIndex: Int { constraints.startIndex } - public var endIndex: Int { constraints.endIndex } - public func index(after i: Int) -> Int { i + 1 } + public nonisolated var startIndex: Int { MainActor.assumeIsolated { constraints.startIndex } } + public nonisolated var endIndex: Int { MainActor.assumeIsolated { constraints.endIndex } } + public nonisolated func index(after i: Int) -> Int { i + 1 } /// Returns all of the created constraints. public private(set) var constraints = [NSLayoutConstraint]() @@ -548,7 +548,6 @@ public final class Constraints: Collection { /// Creates and automatically installs a constraint. static func add(item item1: Any, attribute attr1: NSLayoutConstraint.Attribute, relatedBy relation: NSLayoutConstraint.Relation = .equal, toItem item2: Any? = nil, attribute attr2: NSLayoutConstraint.Attribute? = nil, multiplier: CGFloat = 1, constant: CGFloat = 0) -> NSLayoutConstraint { - precondition(Thread.isMainThread, "Align APIs can only be used from the main thread") #if os(iOS) || os(tvOS) (item1 as? UIView)?.translatesAutoresizingMaskIntoConstraints = false #elseif os(macOS) diff --git a/Tests/AnchorAPIsTests.swift b/Tests/AnchorAPIsTests.swift index 324af52..74a8b86 100644 --- a/Tests/AnchorAPIsTests.swift +++ b/Tests/AnchorAPIsTests.swift @@ -6,13 +6,13 @@ import Foundation import XCTest import Align +@MainActor class AnchorAPITests: XCTestCase { let view = View() let container = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/AnchorAlignmentTests.swift b/Tests/AnchorAlignmentTests.swift index 404f350..d6aee85 100644 --- a/Tests/AnchorAlignmentTests.swift +++ b/Tests/AnchorAlignmentTests.swift @@ -6,15 +6,15 @@ import XCTest import Align /// Everything that applies for both edges and center +@MainActor class AnchorAlignmentTests: XCTestCase { let container = View() let view = View() let a = View() let b = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) container.addSubview(a) container.addSubview(b) diff --git a/Tests/AnchorCenterTests.swift b/Tests/AnchorCenterTests.swift index a41de4f..57e8cb8 100644 --- a/Tests/AnchorCenterTests.swift +++ b/Tests/AnchorCenterTests.swift @@ -5,13 +5,13 @@ import XCTest import Align +@MainActor class AnchorCenterTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/AnchorCollectionCenterTests.swift b/Tests/AnchorCollectionCenterTests.swift index effeabc..3729950 100644 --- a/Tests/AnchorCollectionCenterTests.swift +++ b/Tests/AnchorCollectionCenterTests.swift @@ -5,14 +5,13 @@ import XCTest import Align - +@MainActor class AnchorCollectionCenterTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/AnchorCollectionEdgesTests.swift b/Tests/AnchorCollectionEdgesTests.swift index 692038c..accfa17 100644 --- a/Tests/AnchorCollectionEdgesTests.swift +++ b/Tests/AnchorCollectionEdgesTests.swift @@ -5,13 +5,13 @@ import XCTest import Align +@MainActor class AnchorCollectionEdgesTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/AnchorCollectionSizeTests.swift b/Tests/AnchorCollectionSizeTests.swift index a13275b..3f1eaa5 100644 --- a/Tests/AnchorCollectionSizeTests.swift +++ b/Tests/AnchorCollectionSizeTests.swift @@ -5,13 +5,13 @@ import XCTest import Align +@MainActor class AnchorCollectionSizeTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/AnchorDimensionTests.swift b/Tests/AnchorDimensionTests.swift index 7d1acee..5982562 100644 --- a/Tests/AnchorDimensionTests.swift +++ b/Tests/AnchorDimensionTests.swift @@ -5,13 +5,13 @@ import XCTest import Align +@MainActor class AnchorDimensionTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/AnchorEdgeTests.swift b/Tests/AnchorEdgeTests.swift index 50b0de0..a7fcd04 100644 --- a/Tests/AnchorEdgeTests.swift +++ b/Tests/AnchorEdgeTests.swift @@ -4,18 +4,19 @@ import XCTest import Align +@MainActor class AnchorEdgeTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } // MARK: Pinning + @MainActor func testPinToSuperview() { test("pin top to superview") { let c = view.anchors.top.pin() @@ -41,6 +42,7 @@ class AnchorEdgeTests: XCTestCase { } #if os(iOS) || os(tvOS) + @MainActor func testPinToSuperviewMargin() { test("pin top to superview margin") { let c = view.anchors.top.pin(to: container.layoutMarginsGuide) diff --git a/Tests/AnchorPerformanceTests.swift b/Tests/AnchorPerformanceTests.swift index eeaf110..722007a 100644 --- a/Tests/AnchorPerformanceTests.swift +++ b/Tests/AnchorPerformanceTests.swift @@ -6,6 +6,7 @@ import XCTest import Align // WARNING: Don't forget to compile for Release mode! +@MainActor final class AnchorPerformanceTests: XCTestCase { func testPin() { let view = View() @@ -24,6 +25,10 @@ final class AnchorPerformanceTests: XCTestCase { let container = View() container.addSubview(view) + Constraints(for: view, container) { view, container in + view.top.equal(container.top) + } + measure { Constraints { for _ in 0...10000 { diff --git a/Tests/AnchorTests.swift b/Tests/AnchorTests.swift index cc1c407..5f6729a 100644 --- a/Tests/AnchorTests.swift +++ b/Tests/AnchorTests.swift @@ -5,13 +5,13 @@ import XCTest import Align +@MainActor class AnchorTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } diff --git a/Tests/ConstraintsTests.swift b/Tests/ConstraintsTests.swift index 0664298..4dfbb6e 100644 --- a/Tests/ConstraintsTests.swift +++ b/Tests/ConstraintsTests.swift @@ -5,13 +5,13 @@ import XCTest import Align +@MainActor class ConstraintsTests: XCTestCase { let container = View() let view = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(view) } @@ -42,6 +42,7 @@ class ConstraintsTests: XCTestCase { } } +@MainActor class ConstraintsArityTests: XCTestCase { let container = View() let a = View() @@ -49,9 +50,8 @@ class ConstraintsArityTests: XCTestCase { let c = View() let d = View() - override func setUp() { - super.setUp() - + @MainActor + override func setUp() async throws { container.addSubview(a) container.addSubview(b) container.addSubview(c) @@ -103,18 +103,18 @@ class ConstraintsArityTests: XCTestCase { a.anchors.bottom.pin() } - XCTAssertEqualConstraints(Array(constraints), [ + XCTAssertEqualConstraints(constraints.constraints, [ NSLayoutConstraint(item: a, attribute: .top, toItem: container, attribute: .top), NSLayoutConstraint(item: a, attribute: .bottom, toItem: container, attribute: .bottom) ]) XCTAssertEqualConstraints( - constraints[0], + constraints.constraints[0], NSLayoutConstraint(item: a, attribute: .top, toItem: container, attribute: .top) ) XCTAssertEqualConstraints( - constraints[1], + constraints.constraints[1], NSLayoutConstraint(item: a, attribute: .bottom, toItem: container, attribute: .bottom) ) } @@ -154,6 +154,7 @@ class ConstraintsArityTests: XCTestCase { } #if os(iOS) || os(tvOS) +@MainActor class AddingSubviewsTests: XCTestCase { let container = View() let a = View() diff --git a/Tests/Extensions/Align+Extensions.swift b/Tests/Extensions/Align+Extensions.swift index c66a349..46992a0 100644 --- a/Tests/Extensions/Align+Extensions.swift +++ b/Tests/Extensions/Align+Extensions.swift @@ -16,17 +16,17 @@ public extension UIView { } @discardableResult @nonobjc func addSubview(_ a: UIView, _ b: UIView, constraints: (LayoutAnchors, LayoutAnchors) -> Void) -> Constraints { - [a, b].forEach(addSubview) + [a, b].forEach { addSubview($0) } return Constraints(for: a, b, constraints) } @discardableResult @nonobjc func addSubview(_ a: UIView, _ b: UIView, _ c: UIView, constraints: (LayoutAnchors, LayoutAnchors, LayoutAnchors) -> Void) -> Constraints { - [a, b, c].forEach(addSubview) + [a, b, c].forEach { addSubview($0) } return Constraints(for: a, b, c, constraints) } @discardableResult @nonobjc func addSubview(_ a: UIView, _ b: UIView, _ c: UIView, _ d: UIView, constraints: (LayoutAnchors, LayoutAnchors, LayoutAnchors, LayoutAnchors) -> Void) -> Constraints { - [a, b, c, d].forEach(addSubview) + [a, b, c, d].forEach { addSubview($0) } return Constraints(for: a, b, c, d, constraints) } } diff --git a/Tests/Extensions/XCTestExtensions.swift b/Tests/Extensions/XCTestExtensions.swift index 0b9274f..906e59b 100644 --- a/Tests/Extensions/XCTestExtensions.swift +++ b/Tests/Extensions/XCTestExtensions.swift @@ -14,7 +14,8 @@ func test(_ title: String? = nil, with element: T, _ closure: (T) -> Void) { // MARK: Asserts -public func XCTAssertEqualConstraints(_ expected: [NSLayoutConstraint], _ received: [NSLayoutConstraint], file: StaticString = #file, line: UInt = #line) { +@MainActor +public func XCTAssertEqualConstraints(_ expected: [NSLayoutConstraint], _ received: [NSLayoutConstraint], file: StaticString = #filePath, line: UInt = #line) { XCTAssertEqual(expected.count, received.count, file: file, line: line) var received = received @@ -29,11 +30,13 @@ public func XCTAssertEqualConstraints(_ expected: [NSLayoutConstraint], _ receiv } } -public func XCTAssertEqualConstraints(_ expected: NSLayoutConstraint, _ received: NSLayoutConstraint, file: StaticString = #file, line: UInt = #line) { +@MainActor +public func XCTAssertEqualConstraints(_ expected: NSLayoutConstraint, _ received: NSLayoutConstraint, file: StaticString = #filePath, line: UInt = #line) { XCTAssertEqualConstraints(Constraint(expected), Constraint(received), file: file, line: line) } -private func XCTAssertEqualConstraints(_ expected: T, _ received: T, file: StaticString = #file, line: UInt = #line) { +@MainActor +private func XCTAssertEqualConstraints(_ expected: T, _ received: T, file: StaticString = #filePath, line: UInt = #line) { print(diff(expected, received)) XCTAssertTrue(expected == received, "Found difference for " + diff(expected, received).joined(separator: ", "), file: file, line: line) } @@ -48,7 +51,8 @@ extension NSLayoutConstraint { } } -private struct Constraint: Equatable { +@MainActor +private struct Constraint { let firstItem: AnyObject? let firstAttribute: String let secondItem: AnyObject? @@ -70,7 +74,24 @@ private struct Constraint: Equatable { priority = c.priority.rawValue identifier = c.identifier } +} +#if swift(>=6.0) +extension Constraint: @preconcurrency Equatable { + static func ==(lhs: Constraint, rhs: Constraint) -> Bool { + return lhs.firstItem === rhs.firstItem && + lhs.firstAttribute == rhs.firstAttribute && + lhs.relation == rhs.relation && + lhs.secondItem === rhs.secondItem && + lhs.secondAttribute == rhs.secondAttribute && + lhs.multiplier == rhs.multiplier && + lhs.constant == rhs.constant && + lhs.priority == rhs.priority && + lhs.identifier == rhs.identifier + } +} +#else +extension Constraint: Equatable { static func ==(lhs: Constraint, rhs: Constraint) -> Bool { return lhs.firstItem === rhs.firstItem && lhs.firstAttribute == rhs.firstAttribute && @@ -83,6 +104,7 @@ private struct Constraint: Equatable { lhs.identifier == rhs.identifier } } +#endif // MARK: Helpers