From f791f47ccb95b647bfeffb41cfa22b999f4b6098 Mon Sep 17 00:00:00 2001 From: Dmitriy Holovnia Date: Mon, 30 May 2022 14:17:59 +0300 Subject: [PATCH 01/10] splitting the library into modules --- Package.swift | 14 +++++++++++--- .../Array+extensions.swift | 0 .../CACornerMask+extensions.swift | 0 .../Collection+indexPath.swift | 0 .../NSLayoutConstrain+extensions.swift | 0 .../Protocols/NibInitializable.swift | 0 .../{ => UIKitUptech}/Protocols/ReusableCell.swift | 0 .../UICollectionView+extensions.swift | 0 .../UILayoutPriority+extensions.swift | 0 .../UITableView+extensions.swift | 0 .../UIKit => UIKitUptech}/UIView+extensions.swift | 0 .../Array+extensionsTests.swift | 2 +- .../Collection+indexPathTests.swift | 2 +- .../NSLayoutConstraint+extensionsTests.swift | 2 +- .../UICollectionView+extensionsTests.swift | 2 +- .../UITableView+extensionsTests.swift | 2 +- .../UIView+extensionsTests.swift | 2 +- 17 files changed, 17 insertions(+), 9 deletions(-) rename Sources/Uptech-iOS-Helpers/{Extensions/Foundation => FoundationUptech}/Array+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/CACornerMask+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/Collection+indexPath.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/NSLayoutConstrain+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{ => UIKitUptech}/Protocols/NibInitializable.swift (100%) rename Sources/Uptech-iOS-Helpers/{ => UIKitUptech}/Protocols/ReusableCell.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/UICollectionView+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/UILayoutPriority+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/UITableView+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{Extensions/UIKit => UIKitUptech}/UIView+extensions.swift (100%) rename Tests/Uptech-iOS-Helpers-Tests/{Foundation => FoundationUptech}/Array+extensionsTests.swift (98%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKit => UIKitUptech}/Collection+indexPathTests.swift (95%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKit => UIKitUptech}/NSLayoutConstraint+extensionsTests.swift (96%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKit => UIKitUptech}/UICollectionView+extensionsTests.swift (96%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKit => UIKitUptech}/UITableView+extensionsTests.swift (96%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKit => UIKitUptech}/UIView+extensionsTests.swift (98%) diff --git a/Package.swift b/Package.swift index 4213c72..0e821bd 100644 --- a/Package.swift +++ b/Package.swift @@ -6,10 +6,18 @@ let package = Package( name: "Uptech-iOS-Helpers", platforms: [.iOS(.v11)], products: [ - .library(name: "Uptech-iOS-Helpers", targets: ["Uptech-iOS-Helpers"]), + .library(name: "FoundationUptech", targets: ["FoundationUptech"]), + .library(name: "UIKitUptech", targets: ["UIKitUptech"]) ], targets: [ - .target(name: "Uptech-iOS-Helpers", dependencies: []), - .testTarget(name: "Uptech-iOS-Helpers-Tests", dependencies: ["Uptech-iOS-Helpers"]), + .target(name: "FoundationUptech", path: "Sources/Uptech-iOS-Helpers/FoundationUptech"), + .target(name: "UIKitUptech", path: "Sources/Uptech-iOS-Helpers/UIKitUptech"), + .testTarget(name: "FoundationUptech-Test", + dependencies: ["FoundationUptech"], + path: "Tests/Uptech-iOS-Helpers-Tests/FoundationUptech"), + .testTarget(name: "UIKitUptech-Test", + dependencies: ["UIKitUptech"], + path: "Tests/Uptech-iOS-Helpers-Tests/UIKitUptech") +// .testTarget(name: "Uptech-iOS-Helpers-Tests", dependencies: ["FoundationUptech", "UIKitUptech"]), ] ) diff --git a/Sources/Uptech-iOS-Helpers/Extensions/Foundation/Array+extensions.swift b/Sources/Uptech-iOS-Helpers/FoundationUptech/Array+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/Foundation/Array+extensions.swift rename to Sources/Uptech-iOS-Helpers/FoundationUptech/Array+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/CACornerMask+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/CACornerMask+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/CACornerMask+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/CACornerMask+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/Collection+indexPath.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/Collection+indexPath.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/Collection+indexPath.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/Collection+indexPath.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/NSLayoutConstrain+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/NSLayoutConstrain+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/NSLayoutConstrain+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/NSLayoutConstrain+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/Protocols/NibInitializable.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/NibInitializable.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Protocols/NibInitializable.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/NibInitializable.swift diff --git a/Sources/Uptech-iOS-Helpers/Protocols/ReusableCell.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/ReusableCell.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Protocols/ReusableCell.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/ReusableCell.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/UICollectionView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/UICollectionView+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/UICollectionView+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/UICollectionView+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/UILayoutPriority+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/UILayoutPriority+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/UILayoutPriority+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/UILayoutPriority+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/UITableView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/UITableView+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/UITableView+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/UITableView+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/Extensions/UIKit/UIView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitUptech/UIView+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/Extensions/UIKit/UIView+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitUptech/UIView+extensions.swift diff --git a/Tests/Uptech-iOS-Helpers-Tests/Foundation/Array+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/FoundationUptech/Array+extensionsTests.swift similarity index 98% rename from Tests/Uptech-iOS-Helpers-Tests/Foundation/Array+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/FoundationUptech/Array+extensionsTests.swift index a3bd358..6b054e0 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/Foundation/Array+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/FoundationUptech/Array+extensionsTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import Uptech_iOS_Helpers +@testable import FoundationUptech final class ArrayExtensionsTests: XCTestCase { private let sut = [0, 1, 2, 3, 4] diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKit/Collection+indexPathTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/Collection+indexPathTests.swift similarity index 95% rename from Tests/Uptech-iOS-Helpers-Tests/UIKit/Collection+indexPathTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/Collection+indexPathTests.swift index 8ae87da..fa38546 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKit/Collection+indexPathTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/Collection+indexPathTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import Uptech_iOS_Helpers +@testable import UIKitUptech final class CollectionIndexPathTests: XCTestCase { private let sut = [[0, 1, 2], diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKit/NSLayoutConstraint+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/NSLayoutConstraint+extensionsTests.swift similarity index 96% rename from Tests/Uptech-iOS-Helpers-Tests/UIKit/NSLayoutConstraint+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/NSLayoutConstraint+extensionsTests.swift index 9117f22..1494207 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKit/NSLayoutConstraint+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/NSLayoutConstraint+extensionsTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import Uptech_iOS_Helpers +@testable import UIKitUptech final class NSLayoutConstraintExtensionsTests: XCTestCase { diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKit/UICollectionView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UICollectionView+extensionsTests.swift similarity index 96% rename from Tests/Uptech-iOS-Helpers-Tests/UIKit/UICollectionView+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UICollectionView+extensionsTests.swift index 0448e72..1d34494 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKit/UICollectionView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UICollectionView+extensionsTests.swift @@ -7,7 +7,7 @@ import XCTest import UIKit -@testable import Uptech_iOS_Helpers +@testable import UIKitUptech final class UICollectionViewExtensionsTests: XCTestCase { private class TestCell: UICollectionViewCell, ReusableCell { } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKit/UITableView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UITableView+extensionsTests.swift similarity index 96% rename from Tests/Uptech-iOS-Helpers-Tests/UIKit/UITableView+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UITableView+extensionsTests.swift index 0517f81..83d83e4 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKit/UITableView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UITableView+extensionsTests.swift @@ -7,7 +7,7 @@ import XCTest import UIKit -@testable import Uptech_iOS_Helpers +@testable import UIKitUptech final class UITableViewExtensionsTests: XCTestCase { private class TestCell: UITableViewCell, ReusableCell { } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKit/UIView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UIView+extensionsTests.swift similarity index 98% rename from Tests/Uptech-iOS-Helpers-Tests/UIKit/UIView+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UIView+extensionsTests.swift index 38de2a5..3038826 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKit/UIView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UIView+extensionsTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import Uptech_iOS_Helpers +@testable import UIKitUptech final class UIViewExtensionsTests: XCTestCase { From a5cef8b74a2562eb44d3fe9c1f37baa1729a0189 Mon Sep 17 00:00:00 2001 From: Dmitriy Holovnia Date: Mon, 30 May 2022 14:43:10 +0300 Subject: [PATCH 02/10] rename modules --- Package.swift | 21 +++++++++---------- .../Array+extensions.swift | 0 .../CACornerMask+extensions.swift | 0 .../Collection+indexPath.swift | 0 .../NSLayoutConstrain+extensions.swift | 0 .../Protocols/NibInitializable.swift | 0 .../Protocols/ReusableCell.swift | 0 .../UICollectionView+extensions.swift | 0 .../UILayoutPriority+extensions.swift | 0 .../UITableView+extensions.swift | 0 .../UIView+extensions.swift | 0 .../Array+extensionsTests.swift | 2 +- .../Collection+indexPathTests.swift | 2 +- .../NSLayoutConstraint+extensionsTests.swift | 2 +- .../UICollectionView+extensionsTests.swift | 2 +- .../UITableView+extensionsTests.swift | 2 +- .../UIView+extensionsTests.swift | 2 +- 17 files changed, 16 insertions(+), 17 deletions(-) rename Sources/Uptech-iOS-Helpers/{FoundationUptech => FoundationHelper}/Array+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/CACornerMask+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/Collection+indexPath.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/NSLayoutConstrain+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/Protocols/NibInitializable.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/Protocols/ReusableCell.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/UICollectionView+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/UILayoutPriority+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/UITableView+extensions.swift (100%) rename Sources/Uptech-iOS-Helpers/{UIKitUptech => UIKitHelper}/UIView+extensions.swift (100%) rename Tests/Uptech-iOS-Helpers-Tests/{FoundationUptech => FoundationHelper}/Array+extensionsTests.swift (98%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKitUptech => UIKitHelper}/Collection+indexPathTests.swift (96%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKitUptech => UIKitHelper}/NSLayoutConstraint+extensionsTests.swift (97%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKitUptech => UIKitHelper}/UICollectionView+extensionsTests.swift (97%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKitUptech => UIKitHelper}/UITableView+extensionsTests.swift (96%) rename Tests/Uptech-iOS-Helpers-Tests/{UIKitUptech => UIKitHelper}/UIView+extensionsTests.swift (98%) diff --git a/Package.swift b/Package.swift index 0e821bd..d53b7af 100644 --- a/Package.swift +++ b/Package.swift @@ -6,18 +6,17 @@ let package = Package( name: "Uptech-iOS-Helpers", platforms: [.iOS(.v11)], products: [ - .library(name: "FoundationUptech", targets: ["FoundationUptech"]), - .library(name: "UIKitUptech", targets: ["UIKitUptech"]) + .library(name: "FoundationHelper", targets: ["FoundationHelper"]), + .library(name: "UIKitHelper", targets: ["UIKitHelper"]) ], targets: [ - .target(name: "FoundationUptech", path: "Sources/Uptech-iOS-Helpers/FoundationUptech"), - .target(name: "UIKitUptech", path: "Sources/Uptech-iOS-Helpers/UIKitUptech"), - .testTarget(name: "FoundationUptech-Test", - dependencies: ["FoundationUptech"], - path: "Tests/Uptech-iOS-Helpers-Tests/FoundationUptech"), - .testTarget(name: "UIKitUptech-Test", - dependencies: ["UIKitUptech"], - path: "Tests/Uptech-iOS-Helpers-Tests/UIKitUptech") -// .testTarget(name: "Uptech-iOS-Helpers-Tests", dependencies: ["FoundationUptech", "UIKitUptech"]), + .target(name: "FoundationHelper", path: "Sources/Uptech-iOS-Helpers/FoundationHelper"), + .target(name: "UIKitHelper", path: "Sources/Uptech-iOS-Helpers/UIKitHelper"), + .testTarget(name: "FoundationHelper-Test", + dependencies: ["FoundationHelper"], + path: "Tests/Uptech-iOS-Helpers-Tests/FoundationHelper"), + .testTarget(name: "UIKitHelper-Test", + dependencies: ["UIKitHelper"], + path: "Tests/Uptech-iOS-Helpers-Tests/UIKitHelper") ] ) diff --git a/Sources/Uptech-iOS-Helpers/FoundationUptech/Array+extensions.swift b/Sources/Uptech-iOS-Helpers/FoundationHelper/Array+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/FoundationUptech/Array+extensions.swift rename to Sources/Uptech-iOS-Helpers/FoundationHelper/Array+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/CACornerMask+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/CACornerMask+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/CACornerMask+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/CACornerMask+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/Collection+indexPath.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/Collection+indexPath.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/Collection+indexPath.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/Collection+indexPath.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/NSLayoutConstrain+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/NSLayoutConstrain+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/NSLayoutConstrain+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/NSLayoutConstrain+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/NibInitializable.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/NibInitializable.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/NibInitializable.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/NibInitializable.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/ReusableCell.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/ReusableCell.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/Protocols/ReusableCell.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/ReusableCell.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/UICollectionView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UICollectionView+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/UICollectionView+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/UICollectionView+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/UILayoutPriority+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UILayoutPriority+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/UILayoutPriority+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/UILayoutPriority+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/UITableView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UITableView+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/UITableView+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/UITableView+extensions.swift diff --git a/Sources/Uptech-iOS-Helpers/UIKitUptech/UIView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UIView+extensions.swift similarity index 100% rename from Sources/Uptech-iOS-Helpers/UIKitUptech/UIView+extensions.swift rename to Sources/Uptech-iOS-Helpers/UIKitHelper/UIView+extensions.swift diff --git a/Tests/Uptech-iOS-Helpers-Tests/FoundationUptech/Array+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift similarity index 98% rename from Tests/Uptech-iOS-Helpers-Tests/FoundationUptech/Array+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift index 6b054e0..e5a1485 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/FoundationUptech/Array+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import FoundationUptech +@testable import FoundationHelper final class ArrayExtensionsTests: XCTestCase { private let sut = [0, 1, 2, 3, 4] diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/Collection+indexPathTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift similarity index 96% rename from Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/Collection+indexPathTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift index fa38546..1d8f52a 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/Collection+indexPathTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import UIKitUptech +@testable import UIKitHelper final class CollectionIndexPathTests: XCTestCase { private let sut = [[0, 1, 2], diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/NSLayoutConstraint+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift similarity index 97% rename from Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/NSLayoutConstraint+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift index 1494207..13a62fa 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/NSLayoutConstraint+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import UIKitUptech +@testable import UIKitHelper final class NSLayoutConstraintExtensionsTests: XCTestCase { diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UICollectionView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift similarity index 97% rename from Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UICollectionView+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift index 1d34494..21d46af 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UICollectionView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift @@ -7,7 +7,7 @@ import XCTest import UIKit -@testable import UIKitUptech +@testable import UIKitHelper final class UICollectionViewExtensionsTests: XCTestCase { private class TestCell: UICollectionViewCell, ReusableCell { } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UITableView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift similarity index 96% rename from Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UITableView+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift index 83d83e4..fc62647 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UITableView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift @@ -7,7 +7,7 @@ import XCTest import UIKit -@testable import UIKitUptech +@testable import UIKitHelper final class UITableViewExtensionsTests: XCTestCase { private class TestCell: UITableViewCell, ReusableCell { } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UIView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift similarity index 98% rename from Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UIView+extensionsTests.swift rename to Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift index 3038826..37ee737 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitUptech/UIView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift @@ -6,7 +6,7 @@ // import XCTest -@testable import UIKitUptech +@testable import UIKitHelper final class UIViewExtensionsTests: XCTestCase { From 0122357151430270c938886a48339bc4ecf71a06 Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Fri, 2 Aug 2024 17:58:23 +0300 Subject: [PATCH 03/10] updated targets names changed indentation throughout the package --- Package.swift | 32 ++-- .../FoundationHelper/Array+extensions.swift | 114 ++++++------ .../UIKitHelper/CACornerMask+extensions.swift | 16 +- .../UIKitHelper/Collection+indexPath.swift | 14 +- .../NSLayoutConstrain+extensions.swift | 26 +-- .../Protocols/NibInitializable.swift | 47 +++-- .../UIKitHelper/Protocols/ReusableCell.swift | 12 +- .../UICollectionView+extensions.swift | 52 +++--- .../UILayoutPriority+extensions.swift | 12 +- .../UIKitHelper/UITableView+extensions.swift | 52 +++--- .../UIKitHelper/UIView+extensions.swift | 130 ++++++------- .../Array+extensionsTests.swift | 172 +++++++++--------- .../Collection+indexPathTests.swift | 52 +++--- .../NSLayoutConstraint+extensionsTests.swift | 50 ++--- .../UICollectionView+extensionsTests.swift | 42 ++--- .../UITableView+extensionsTests.swift | 36 ++-- .../UIKitHelper/UIView+extensionsTests.swift | 126 ++++++------- 17 files changed, 491 insertions(+), 494 deletions(-) diff --git a/Package.swift b/Package.swift index d53b7af..44cef8b 100644 --- a/Package.swift +++ b/Package.swift @@ -3,20 +3,20 @@ import PackageDescription let package = Package( - name: "Uptech-iOS-Helpers", - platforms: [.iOS(.v11)], - products: [ - .library(name: "FoundationHelper", targets: ["FoundationHelper"]), - .library(name: "UIKitHelper", targets: ["UIKitHelper"]) - ], - targets: [ - .target(name: "FoundationHelper", path: "Sources/Uptech-iOS-Helpers/FoundationHelper"), - .target(name: "UIKitHelper", path: "Sources/Uptech-iOS-Helpers/UIKitHelper"), - .testTarget(name: "FoundationHelper-Test", - dependencies: ["FoundationHelper"], - path: "Tests/Uptech-iOS-Helpers-Tests/FoundationHelper"), - .testTarget(name: "UIKitHelper-Test", - dependencies: ["UIKitHelper"], - path: "Tests/Uptech-iOS-Helpers-Tests/UIKitHelper") - ] + name: "Uptech-iOS-Helpers", + platforms: [.iOS(.v13)], + products: [ + .library(name: "UptechFoundationHelper", targets: ["UptechFoundationHelper"]), + .library(name: "UptechUIKitHelper", targets: ["UptechUIKitHelper"]) + ], + targets: [ + .target(name: "UptechFoundationHelper", path: "Sources/Uptech-iOS-Helpers/FoundationHelper"), + .target(name: "UptechUIKitHelper", path: "Sources/Uptech-iOS-Helpers/UIKitHelper"), + .testTarget(name: "FoundationHelper-Test", + dependencies: ["UptechFoundationHelper"], + path: "Tests/Uptech-iOS-Helpers-Tests/FoundationHelper"), + .testTarget(name: "UIKitHelper-Test", + dependencies: ["UptechUIKitHelper"], + path: "Tests/Uptech-iOS-Helpers-Tests/UIKitHelper") + ] ) diff --git a/Sources/Uptech-iOS-Helpers/FoundationHelper/Array+extensions.swift b/Sources/Uptech-iOS-Helpers/FoundationHelper/Array+extensions.swift index 27155d0..ebd93af 100644 --- a/Sources/Uptech-iOS-Helpers/FoundationHelper/Array+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/FoundationHelper/Array+extensions.swift @@ -1,69 +1,67 @@ // // Array+extensions.swift -// +// // // Created by Sergey Kletsov on 25.03.2022. // -import Foundation - public extension Array { - /// Returns the element at the specified index if it is within bounds, otherwise nil. - subscript(safe index: Index) -> Element? { - indices.contains(index) ? self[index] : nil - } - - /// Returns the elements at the specified range if it is within bounds, otherwise empty array. - subscript(safe range: Range) -> [Element] { - guard - range.startIndex >= startIndex, - range.endIndex <= endIndex else { - return [] - } - - return Array(self[range]) - } - - /// Returns the elements at the specified closed range if it is within bounds, otherwise empty array. - subscript(safe range: ClosedRange) -> [Element] { - guard - range.lowerBound >= 0, - endIndex > 0, - range.upperBound <= endIndex else { - return [] - } - - let maxIndex = endIndex - 1 - let upperBound = Swift.min(range.upperBound, maxIndex) - return Array(self[range.lowerBound...upperBound]) - } + /// Returns the element at the specified index if it is within bounds, otherwise nil. + subscript(safe index: Index) -> Element? { + indices.contains(index) ? self[index] : nil + } + + /// Returns the elements at the specified range if it is within bounds, otherwise empty array. + subscript(safe range: Range) -> [Element] { + guard + range.startIndex >= startIndex, + range.endIndex <= endIndex else { + return [] + } + + return Array(self[range]) + } + + /// Returns the elements at the specified closed range if it is within bounds, otherwise empty array. + subscript(safe range: ClosedRange) -> [Element] { + guard + range.lowerBound >= 0, + endIndex > 0, + range.upperBound <= endIndex else { + return [] + } + + let maxIndex = endIndex - 1 + let upperBound = Swift.min(range.upperBound, maxIndex) + return Array(self[range.lowerBound...upperBound]) + } } public extension Array where Element: Equatable { - /// Removes first element in array. - /// - Parameter item: An element to remove. - mutating func remove(_ item: Element) { - guard let index = firstIndex(of: item) else { return } - remove(at: index) - } - - /// Returns next element in array after a given one. - /// - Parameter item: An element to search next element. - /// - Returns: Element after passed item. If passed item is last element in array will return nil. - func next(item: Element) -> Element? { - if let index = self.firstIndex(of: item) { - return self[safe: index + 1] - } - return nil - } - - /// Returns previous element in array before a given one. - /// - Parameter item: An element to search previous element. - /// - Returns: Element before passed item. If passed item is first element in array will return nil. - func previous(item: Element) -> Element? { - if let index = self.firstIndex(of: item) { - return self[safe: index - 1] - } - return nil - } + /// Removes first element in array. + /// - Parameter item: An element to remove. + mutating func remove(_ item: Element) { + guard let index = firstIndex(of: item) else { return } + remove(at: index) + } + + /// Returns next element in array after a given one. + /// - Parameter item: An element to search next element. + /// - Returns: Element after passed item. If passed item is last element in array will return nil. + func next(item: Element) -> Element? { + if let index = self.firstIndex(of: item) { + return self[safe: index + 1] + } + return nil + } + + /// Returns previous element in array before a given one. + /// - Parameter item: An element to search previous element. + /// - Returns: Element before passed item. If passed item is first element in array will return nil. + func previous(item: Element) -> Element? { + if let index = self.firstIndex(of: item) { + return self[safe: index - 1] + } + return nil + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/CACornerMask+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/CACornerMask+extensions.swift index 9d8f9ac..70075b3 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/CACornerMask+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/CACornerMask+extensions.swift @@ -1,6 +1,6 @@ // // CACornerMask+extensions.swift -// +// // // Created by Sergey Kletsov on 25.03.2022. // @@ -8,11 +8,11 @@ import UIKit public extension CACornerMask { - /// Contains all corner masks (MaxXMaxY, MinXMaxY, MaxXMinY, MinXMinY). - static let all: CACornerMask = [ - CACornerMask.layerMaxXMaxYCorner, - CACornerMask.layerMinXMaxYCorner, - CACornerMask.layerMaxXMinYCorner, - CACornerMask.layerMinXMinYCorner - ] + /// Contains all corner masks (MaxXMaxY, MinXMaxY, MaxXMinY, MinXMinY). + static let all: CACornerMask = [ + CACornerMask.layerMaxXMaxYCorner, + CACornerMask.layerMinXMaxYCorner, + CACornerMask.layerMaxXMinYCorner, + CACornerMask.layerMinXMinYCorner + ] } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/Collection+indexPath.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/Collection+indexPath.swift index 9e8ce69..f3c83a0 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/Collection+indexPath.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/Collection+indexPath.swift @@ -1,6 +1,6 @@ // // Collection+indexPath.swift -// +// // // Created by Sergey Kletsov on 25.03.2022. // @@ -8,10 +8,10 @@ import UIKit public extension Collection where Index == Int, Iterator.Element: Collection, Iterator.Element.Index == Int { - /// Returns Element in two dimensional array by IndexPath. - /// - Parameter indexPath: An IndexPath to get Element by section and row. - /// - Returns: Element by given indexPath. - subscript(indexPath: IndexPath) -> Iterator.Element.Iterator.Element { - self[indexPath.section][indexPath.row] - } + /// Returns Element in two dimensional array by IndexPath. + /// - Parameter indexPath: An IndexPath to get Element by section and row. + /// - Returns: Element by given indexPath. + subscript(indexPath: IndexPath) -> Iterator.Element.Iterator.Element { + self[indexPath.section][indexPath.row] + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/NSLayoutConstrain+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/NSLayoutConstrain+extensions.swift index acc84b6..2d6a459 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/NSLayoutConstrain+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/NSLayoutConstrain+extensions.swift @@ -1,6 +1,6 @@ // // NSLayoutConstrain+extensions.swift -// +// // // Created by Sergey Kletsov on 25.03.2022. // @@ -8,19 +8,19 @@ import UIKit public extension NSLayoutConstraint { - @discardableResult - /// Returns self with given priority. - /// - Parameter priority: UILayoutPriority to set. - /// - Returns: self. - func withPriority(_ priority: UILayoutPriority) -> NSLayoutConstraint { - self.priority = priority - return self - } + @discardableResult + /// Returns self with given priority. + /// - Parameter priority: UILayoutPriority to set. + /// - Returns: self. + func withPriority(_ priority: UILayoutPriority) -> NSLayoutConstraint { + self.priority = priority + return self + } } public extension Array where Element == NSLayoutConstraint { - /// Activates each constraint in self - func activate() { - NSLayoutConstraint.activate(self) - } + /// Activates each constraint in self + func activate() { + NSLayoutConstraint.activate(self) + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/NibInitializable.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/NibInitializable.swift index bef868c..a9ee774 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/NibInitializable.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/NibInitializable.swift @@ -1,39 +1,38 @@ // // NibInitializable.swift -// +// // // Created by Sergey Kletsov on 28.03.2022. // -import Foundation import UIKit /// Protocol that helps to initialize view with xib. /// All properties and method have default implementation. public protocol NibInitializable { - /// Default implementation returns class name. - static var nibName: String { get } - /// Default implementation returns nib with self.nibName in default bundle. - static var nib: UINib { get } - /// Returns view initiated from xib - /// - Returns: Default implementation returns first view in self.nib casted to Self. - static func initFromNib() -> Self + /// Default implementation returns class name. + static var nibName: String { get } + /// Default implementation returns nib with self.nibName in default bundle. + static var nib: UINib { get } + /// Returns view initiated from xib + /// - Returns: Default implementation returns first view in self.nib casted to Self. + static func initFromNib() -> Self } public extension NibInitializable where Self: UIView { - static var nibName: String { - String(describing: Self.self) - } - - static var nib: UINib { - UINib(nibName: nibName, bundle: nil) - } - - static func initFromNib() -> Self { - guard let view = nib.instantiate(withOwner: nil, options: nil).first as? Self else { - fatalError("Could not instantiate view from nib with name \(nibName).") - } - - return view - } + static var nibName: String { + String(describing: Self.self) + } + + static var nib: UINib { + UINib(nibName: nibName, bundle: nil) + } + + static func initFromNib() -> Self { + guard let view = nib.instantiate(withOwner: nil, options: nil).first as? Self else { + fatalError("Could not instantiate view from nib with name \(nibName).") + } + + return view + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/ReusableCell.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/ReusableCell.swift index 0574479..eb32886 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/ReusableCell.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/Protocols/ReusableCell.swift @@ -1,6 +1,6 @@ // // ReusableCell.swift -// +// // // Created by Sergey Kletsov on 28.03.2022. // @@ -10,12 +10,12 @@ import UIKit /// Protocol that helps with reusable cells. If used on UITableViewCell subclasses provides handy methods for registering and dequeueing cells in UITableView's /// Has default implementation for reuseIdentifier. public protocol ReusableCell { - /// Default implementation return's class name - static var reuseIdentifier: String { get } + /// Default implementation return's class name + static var reuseIdentifier: String { get } } public extension ReusableCell { - static var reuseIdentifier: String { - String(describing: Self.self) - } + static var reuseIdentifier: String { + String(describing: Self.self) + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/UICollectionView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UICollectionView+extensions.swift index f608129..a406063 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/UICollectionView+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/UICollectionView+extensions.swift @@ -1,6 +1,6 @@ // // UICollectionView+extensions.swift -// +// // // Created by Sergey Kletsov on 05.04.2022. // @@ -8,29 +8,29 @@ import UIKit public extension UICollectionView { - /// Dequeue's reusable cell for index path with given cell type. - /// - Important: Will crash if cell type for given reuseIdentifier don't match passed cellType! - /// - Parameters: - /// - indexPath: The index path specifying the location of the cell. - /// - cellType: Type of cell that should be dequeued. Must be ReusableCell. - /// - Returns: UICollectionViewCell dequeued and cased to cellType. - func dequeueReusableCell(for indexPath: IndexPath, cellType: T.Type = T.self) -> T where T: ReusableCell { - guard let cell = self.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { - fatalError("Failed to dequeue a cell with identifier \(cellType.reuseIdentifier) matching type \(cellType.self).") - } - - return cell - } - - /// Registers a class to use in creating new table cells by cellType.reuseIdentifier. - /// - Parameter cellType: Cell type that will be registered by cellType.reuseIdentifier - func register(_ cellType: T.Type) where T: ReusableCell { - self.register(cellType.self, forCellWithReuseIdentifier: cellType.reuseIdentifier) - } - - /// Registers a nib object that contains a cell with the table view under a specified identifier by cellType.reuseIdentifier. - /// - Parameter cellType: Cell type, nib of witch will be registered by cellType.reuseIdentifier. - func register(_ cellType: T.Type) where T: ReusableCell & NibInitializable { - self.register(cellType.nib, forCellWithReuseIdentifier: cellType.reuseIdentifier) - } + /// Dequeue's reusable cell for index path with given cell type. + /// - Important: Will crash if cell type for given reuseIdentifier don't match passed cellType! + /// - Parameters: + /// - indexPath: The index path specifying the location of the cell. + /// - cellType: Type of cell that should be dequeued. Must be ReusableCell. + /// - Returns: UICollectionViewCell dequeued and cased to cellType. + func dequeueReusableCell(for indexPath: IndexPath, cellType: T.Type = T.self) -> T where T: ReusableCell { + guard let cell = self.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { + fatalError("Failed to dequeue a cell with identifier \(cellType.reuseIdentifier) matching type \(cellType.self).") + } + + return cell + } + + /// Registers a class to use in creating new table cells by cellType.reuseIdentifier. + /// - Parameter cellType: Cell type that will be registered by cellType.reuseIdentifier + func register(_ cellType: T.Type) where T: ReusableCell { + self.register(cellType.self, forCellWithReuseIdentifier: cellType.reuseIdentifier) + } + + /// Registers a nib object that contains a cell with the table view under a specified identifier by cellType.reuseIdentifier. + /// - Parameter cellType: Cell type, nib of witch will be registered by cellType.reuseIdentifier. + func register(_ cellType: T.Type) where T: ReusableCell & NibInitializable { + self.register(cellType.nib, forCellWithReuseIdentifier: cellType.reuseIdentifier) + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/UILayoutPriority+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UILayoutPriority+extensions.swift index 0df979d..e40ca7a 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/UILayoutPriority+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/UILayoutPriority+extensions.swift @@ -8,10 +8,10 @@ import UIKit public extension UILayoutPriority { - /// rawValue 999 - static let almostRequired = UILayoutPriority(999) - /// rawValue 751 - static let prioritizedCompressionResistance = UILayoutPriority(751) - /// rawValue 251 - static let prioritizedHugging = UILayoutPriority(251) + /// rawValue 999 + static let almostRequired = UILayoutPriority(999) + /// rawValue 751 + static let prioritizedCompressionResistance = UILayoutPriority(751) + /// rawValue 251 + static let prioritizedHugging = UILayoutPriority(251) } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/UITableView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UITableView+extensions.swift index 2349137..8d44675 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/UITableView+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/UITableView+extensions.swift @@ -1,6 +1,6 @@ // // UITableView+extensions.swift -// +// // // Created by Sergey Kletsov on 05.04.2022. // @@ -8,29 +8,29 @@ import UIKit public extension UITableView { - /// Dequeue's reusable cell for index path with given cell type. - /// - Important: Will crash if cell type for given reuseIdentifier don't match passed cellType! - /// - Parameters: - /// - indexPath: The index path specifying the location of the cell. - /// - cellType: Type of cell that should be dequeued. Must be ReusableCell. - /// - Returns: UITableViewCell dequeued and cased to cellType. - func dequeueReusableCell(for indexPath: IndexPath, cellType: T.Type = T.self) -> T where T: ReusableCell { - guard let cell = self.dequeueReusableCell(withIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { - fatalError("Failed to dequeue a cell with identifier \(cellType.reuseIdentifier) matching type \(cellType.self).") - } - - return cell - } - - /// Registers a class to use in creating new table cells by cellType.reuseIdentifier. - /// - Parameter cellType: Cell type that will be registered by cellType.reuseIdentifier - func register(_ cellType: T.Type) where T: ReusableCell { - self.register(cellType.self, forCellReuseIdentifier: cellType.reuseIdentifier) - } - - /// Registers a nib object that contains a cell with the table view under a specified identifier by cellType.reuseIdentifier. - /// - Parameter cellType: Cell type, nib of witch will be registered by cellType.reuseIdentifier. - func register(_ cellType: T.Type) where T: ReusableCell & NibInitializable { - self.register(cellType.nib, forCellReuseIdentifier: cellType.reuseIdentifier) - } + /// Dequeue's reusable cell for index path with given cell type. + /// - Important: Will crash if cell type for given reuseIdentifier don't match passed cellType! + /// - Parameters: + /// - indexPath: The index path specifying the location of the cell. + /// - cellType: Type of cell that should be dequeued. Must be ReusableCell. + /// - Returns: UITableViewCell dequeued and cased to cellType. + func dequeueReusableCell(for indexPath: IndexPath, cellType: T.Type = T.self) -> T where T: ReusableCell { + guard let cell = self.dequeueReusableCell(withIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { + fatalError("Failed to dequeue a cell with identifier \(cellType.reuseIdentifier) matching type \(cellType.self).") + } + + return cell + } + + /// Registers a class to use in creating new table cells by cellType.reuseIdentifier. + /// - Parameter cellType: Cell type that will be registered by cellType.reuseIdentifier + func register(_ cellType: T.Type) where T: ReusableCell { + self.register(cellType.self, forCellReuseIdentifier: cellType.reuseIdentifier) + } + + /// Registers a nib object that contains a cell with the table view under a specified identifier by cellType.reuseIdentifier. + /// - Parameter cellType: Cell type, nib of witch will be registered by cellType.reuseIdentifier. + func register(_ cellType: T.Type) where T: ReusableCell & NibInitializable { + self.register(cellType.nib, forCellReuseIdentifier: cellType.reuseIdentifier) + } } diff --git a/Sources/Uptech-iOS-Helpers/UIKitHelper/UIView+extensions.swift b/Sources/Uptech-iOS-Helpers/UIKitHelper/UIView+extensions.swift index 89c37a3..c0cac35 100644 --- a/Sources/Uptech-iOS-Helpers/UIKitHelper/UIView+extensions.swift +++ b/Sources/Uptech-iOS-Helpers/UIKitHelper/UIView+extensions.swift @@ -1,74 +1,74 @@ // // UIView+extensions.swift -// +// // // Created by Sergey Kletsov on 25.03.2022. // import UIKit public extension UIView { - /// Adds a view as subview the self. - /// Set's view translatesAutoresizingMaskIntoConstraints to false. - /// Activates given constrains array. - /// - Parameters: - /// - view: View to add as subview and disable Autoresizing Mask. - /// - constraints: Constrains array to activate after adding subview and disabling Autoresizing Mask. - func addSubview( _ view: UIView, withConstraints constraints: [NSLayoutConstraint]) { - addSubview(view) - view.translatesAutoresizingMaskIntoConstraints = false - constraints.activate() - } - - /// Adds a view as subview the self. - /// Adds constrains that fill given view to self's bounds. - /// - Also will set given view's translatesAutoresizingMaskIntoConstraints to false. - /// - Parameter view: View to add as subview and fill to self's bounds. - func addSubviewWithEdgeConstraints(_ view: UIView) { - addSubview(view, withConstraints: [ - view.topAnchor.constraint(equalTo: topAnchor), - view.leadingAnchor.constraint(equalTo: leadingAnchor), - view.trailingAnchor.constraint(equalTo: trailingAnchor), - view.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - } - - /// Inserts a view to self at given index with given constrains. - /// - Also will set given view's translatesAutoresizingMaskIntoConstraints to false. - /// - Parameters: - /// - view: View to insert as subview and disable Autoresizing Mask. - /// - index: The index in the array of the subviews property at which to insert the view. Default value .zero - /// - constraints: Constrains array to activate after adding subview and disabling Autoresizing Mask. - func insertSubview(_ view: UIView, at index: Int = .zero, withConstraints constraints: [NSLayoutConstraint] ) { - insertSubview(view, at: index) - view.translatesAutoresizingMaskIntoConstraints = false - constraints.activate() - } - - /// Inserts a view as subview the self. - /// Adds constrains that fill given view to self's bounds. - /// - Also will set given view's translatesAutoresizingMaskIntoConstraints to false. - /// - Parameters: - /// - view: View to insert as subview and fill to self's bounds. - /// - index: The index in the array of the subviews property at which to insert the view. Default value .zero - func insertSubviewWithEdgeConstraints(_ view: UIView, at index: Int = .zero) { - insertSubview(view, at: index, withConstraints: [ - view.topAnchor.constraint(equalTo: topAnchor), - view.leadingAnchor.constraint(equalTo: leadingAnchor), - view.trailingAnchor.constraint(equalTo: trailingAnchor), - view.bottomAnchor.constraint(equalTo: bottomAnchor), - ]) - } - - /// Adds corner radius to given corners. - /// - Parameters: - /// - radius: Corner radius to add. - /// - corners: Corners to add corner radius to. Default value .all - func roundCornersContinuously(radius: CGFloat, corners: CACornerMask = .all) { - layer.maskedCorners = corners - layer.cornerRadius = radius - - if #available(iOS 13.0, *) { - layer.cornerCurve = .continuous - } - } + /// Adds a view as subview the self. + /// Set's view translatesAutoresizingMaskIntoConstraints to false. + /// Activates given constrains array. + /// - Parameters: + /// - view: View to add as subview and disable Autoresizing Mask. + /// - constraints: Constrains array to activate after adding subview and disabling Autoresizing Mask. + func addSubview( _ view: UIView, withConstraints constraints: [NSLayoutConstraint]) { + addSubview(view) + view.translatesAutoresizingMaskIntoConstraints = false + constraints.activate() + } + + /// Adds a view as subview the self. + /// Adds constrains that fill given view to self's bounds. + /// - Also will set given view's translatesAutoresizingMaskIntoConstraints to false. + /// - Parameter view: View to add as subview and fill to self's bounds. + func addSubviewWithEdgeConstraints(_ view: UIView) { + addSubview(view, withConstraints: [ + view.topAnchor.constraint(equalTo: topAnchor), + view.leadingAnchor.constraint(equalTo: leadingAnchor), + view.trailingAnchor.constraint(equalTo: trailingAnchor), + view.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + } + + /// Inserts a view to self at given index with given constrains. + /// - Also will set given view's translatesAutoresizingMaskIntoConstraints to false. + /// - Parameters: + /// - view: View to insert as subview and disable Autoresizing Mask. + /// - index: The index in the array of the subviews property at which to insert the view. Default value .zero + /// - constraints: Constrains array to activate after adding subview and disabling Autoresizing Mask. + func insertSubview(_ view: UIView, at index: Int = .zero, withConstraints constraints: [NSLayoutConstraint] ) { + insertSubview(view, at: index) + view.translatesAutoresizingMaskIntoConstraints = false + constraints.activate() + } + + /// Inserts a view as subview the self. + /// Adds constrains that fill given view to self's bounds. + /// - Also will set given view's translatesAutoresizingMaskIntoConstraints to false. + /// - Parameters: + /// - view: View to insert as subview and fill to self's bounds. + /// - index: The index in the array of the subviews property at which to insert the view. Default value .zero + func insertSubviewWithEdgeConstraints(_ view: UIView, at index: Int = .zero) { + insertSubview(view, at: index, withConstraints: [ + view.topAnchor.constraint(equalTo: topAnchor), + view.leadingAnchor.constraint(equalTo: leadingAnchor), + view.trailingAnchor.constraint(equalTo: trailingAnchor), + view.bottomAnchor.constraint(equalTo: bottomAnchor), + ]) + } + + /// Adds corner radius to given corners. + /// - Parameters: + /// - radius: Corner radius to add. + /// - corners: Corners to add corner radius to. Default value .all + func roundCornersContinuously(radius: CGFloat, corners: CACornerMask = .all) { + layer.maskedCorners = corners + layer.cornerRadius = radius + + if #available(iOS 13.0, *) { + layer.cornerCurve = .continuous + } + } } diff --git a/Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift index e5a1485..642ed5e 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/FoundationHelper/Array+extensionsTests.swift @@ -1,96 +1,96 @@ // // Array+extensionsTests.swift -// +// // // Created by Sergey Kletsov on 25.03.2022. // import XCTest -@testable import FoundationHelper +@testable import UptechFoundationHelper final class ArrayExtensionsTests: XCTestCase { - private let sut = [0, 1, 2, 3, 4] - - func testSafeElementReturnsElement() throws { - let result = sut[safe: 2] - let expectedResult = 2 - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testSafeElementReturnsNil() throws { - let result = sut[safe: 10] - XCTAssertNil(result, "Result should be nil") - } - - func testSafeRangeReturnsElements() throws { - let result = sut[safe: 1..<3] - let expectedResult = [1, 2] - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testSafeNegativeRangeReturnsEmpty() throws { - let result = sut[safe: -3..<(-1)] - let expectedResult: [Int] = [] - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testSafeRangeReturnsEmpty() throws { - let result = sut[safe: 7..<10] - let expectedResult: [Int] = [] - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testSafeClosedRangeReturnsElements() throws { - let result = sut[safe: 1...3] - let expectedResult = [1, 2, 3] - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testSafeNegativeClosedRangeReturnsEmpty() throws { - let result = sut[safe: -3...(-1)] - let expectedResult: [Int] = [] - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testSafeClosedRangeReturnsEmpty() throws { - let result = sut[safe: 7...10] - let expectedResult: [Int] = [] - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testRemoveExistingElement() throws { - var sut = self.sut - sut.remove(1) - let expectedResult = [0, 2, 3, 4] - XCTAssertEqual(sut, expectedResult, "Result should be \(expectedResult)") - } - - func testRemoveNonExistingElement() throws { - var sut = self.sut - sut.remove(5) - let expectedResult = self.sut - XCTAssertEqual(sut, expectedResult, "Result should be \(expectedResult)") - } - - func testNextElementExist() throws { - let result = sut.next(item: 2) - let expectedResult = 3 - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testNextElementNil() throws { - let result = sut.next(item: 4) - XCTAssertNil(result, "Result should be nil") - } - - func testPreviousElementExist() throws { - let result = sut.previous(item: 2) - let expectedResult = 1 - XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") - } - - func testPreviousElementNil() throws { - let result = sut.previous(item: 0) - XCTAssertNil(result, "Result should be nil") - } + private let sut = [0, 1, 2, 3, 4] + + func testSafeElementReturnsElement() throws { + let result = sut[safe: 2] + let expectedResult = 2 + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testSafeElementReturnsNil() throws { + let result = sut[safe: 10] + XCTAssertNil(result, "Result should be nil") + } + + func testSafeRangeReturnsElements() throws { + let result = sut[safe: 1..<3] + let expectedResult = [1, 2] + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testSafeNegativeRangeReturnsEmpty() throws { + let result = sut[safe: -3..<(-1)] + let expectedResult: [Int] = [] + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testSafeRangeReturnsEmpty() throws { + let result = sut[safe: 7..<10] + let expectedResult: [Int] = [] + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testSafeClosedRangeReturnsElements() throws { + let result = sut[safe: 1...3] + let expectedResult = [1, 2, 3] + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testSafeNegativeClosedRangeReturnsEmpty() throws { + let result = sut[safe: -3...(-1)] + let expectedResult: [Int] = [] + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testSafeClosedRangeReturnsEmpty() throws { + let result = sut[safe: 7...10] + let expectedResult: [Int] = [] + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testRemoveExistingElement() throws { + var sut = self.sut + sut.remove(1) + let expectedResult = [0, 2, 3, 4] + XCTAssertEqual(sut, expectedResult, "Result should be \(expectedResult)") + } + + func testRemoveNonExistingElement() throws { + var sut = self.sut + sut.remove(5) + let expectedResult = self.sut + XCTAssertEqual(sut, expectedResult, "Result should be \(expectedResult)") + } + + func testNextElementExist() throws { + let result = sut.next(item: 2) + let expectedResult = 3 + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testNextElementNil() throws { + let result = sut.next(item: 4) + XCTAssertNil(result, "Result should be nil") + } + + func testPreviousElementExist() throws { + let result = sut.previous(item: 2) + let expectedResult = 1 + XCTAssertEqual(result, expectedResult, "Result should be \(expectedResult)") + } + + func testPreviousElementNil() throws { + let result = sut.previous(item: 0) + XCTAssertNil(result, "Result should be nil") + } } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift index 1d8f52a..ac051ca 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/Collection+indexPathTests.swift @@ -6,32 +6,32 @@ // import XCTest -@testable import UIKitHelper +@testable import UptechUIKitHelper final class CollectionIndexPathTests: XCTestCase { - private let sut = [[0, 1, 2], - [3, 4, 5], - [6, 7, 8]] - - func testIndexPathSubscriptFirstItem() { - let result = sut[IndexPath(item: 0, section: 0)] - let expectedResult = 0 - - XCTAssertEqual(result, expectedResult) - } - - func testIndexPathSubscriptMiddleItem() { - let result = sut[IndexPath(row: 1, section: 1)] - let expectedResult = 4 - - XCTAssertEqual(result, expectedResult) - } - - func testIndexPathSubscriptLastItem() { - let result = sut[IndexPath(item: 2, section: 2)] - let expectedResult = 8 - - XCTAssertEqual(result, expectedResult) - } - + private let sut = [[0, 1, 2], + [3, 4, 5], + [6, 7, 8]] + + func testIndexPathSubscriptFirstItem() { + let result = sut[IndexPath(item: 0, section: 0)] + let expectedResult = 0 + + XCTAssertEqual(result, expectedResult) + } + + func testIndexPathSubscriptMiddleItem() { + let result = sut[IndexPath(row: 1, section: 1)] + let expectedResult = 4 + + XCTAssertEqual(result, expectedResult) + } + + func testIndexPathSubscriptLastItem() { + let result = sut[IndexPath(item: 2, section: 2)] + let expectedResult = 8 + + XCTAssertEqual(result, expectedResult) + } + } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift index 13a62fa..9d2c266 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/NSLayoutConstraint+extensionsTests.swift @@ -6,31 +6,31 @@ // import XCTest -@testable import UIKitHelper +@testable import UptechUIKitHelper final class NSLayoutConstraintExtensionsTests: XCTestCase { - - func testWithPriority() throws { - let sut = NSLayoutConstraint() - let priority = UILayoutPriority.almostRequired - let result = sut.withPriority(priority) - XCTAssertEqual(result.priority, priority, "sut's priority should be \(priority)") - } - - func testActivateExtension() throws { - let rootView = UIView() - let subview = UIView() - - subview.translatesAutoresizingMaskIntoConstraints = false - rootView.addSubview(subview) - - let sut = [subview.heightAnchor.constraint(equalToConstant: 100), - subview.widthAnchor.constraint(equalTo: rootView.widthAnchor), - subview.centerYAnchor.constraint(equalTo: rootView.centerYAnchor), - subview.centerXAnchor.constraint(equalTo: rootView.centerXAnchor)] - - sut.activate() - XCTAssertTrue(sut.allSatisfy(\.isActive), "all constrains in sut array should be activated") - } - + + func testWithPriority() throws { + let sut = NSLayoutConstraint() + let priority = UILayoutPriority.almostRequired + let result = sut.withPriority(priority) + XCTAssertEqual(result.priority, priority, "sut's priority should be \(priority)") + } + + func testActivateExtension() throws { + let rootView = UIView() + let subview = UIView() + + subview.translatesAutoresizingMaskIntoConstraints = false + rootView.addSubview(subview) + + let sut = [subview.heightAnchor.constraint(equalToConstant: 100), + subview.widthAnchor.constraint(equalTo: rootView.widthAnchor), + subview.centerYAnchor.constraint(equalTo: rootView.centerYAnchor), + subview.centerXAnchor.constraint(equalTo: rootView.centerXAnchor)] + + sut.activate() + XCTAssertTrue(sut.allSatisfy(\.isActive), "all constrains in sut array should be activated") + } + } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift index 21d46af..72b5c5d 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UICollectionView+extensionsTests.swift @@ -7,27 +7,27 @@ import XCTest import UIKit -@testable import UIKitHelper +@testable import UptechUIKitHelper final class UICollectionViewExtensionsTests: XCTestCase { - private class TestCell: UICollectionViewCell, ReusableCell { } - private let cellType = TestCell.self - - func testRegisterCorrectType() throws { - let collectionView = createCollectionView() - collectionView.register(cellType) - let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: .init(item: 0, section: 0)) - let isCellRightType = cell.isKind(of: cellType) - XCTAssertTrue(isCellRightType, "dequeued cell must be \(cellType)") - } - - func testDequeueNotCrashing() { - let collectionView = createCollectionView() - collectionView.register(cellType, forCellWithReuseIdentifier: cellType.reuseIdentifier) - let _ = collectionView.dequeueReusableCell(for: .init(item: 0, section: 0), cellType: cellType) - } - - private func createCollectionView() -> UICollectionView { - UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout()) - } + private class TestCell: UICollectionViewCell, ReusableCell { } + private let cellType = TestCell.self + + func testRegisterCorrectType() throws { + let collectionView = createCollectionView() + collectionView.register(cellType) + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: .init(item: 0, section: 0)) + let isCellRightType = cell.isKind(of: cellType) + XCTAssertTrue(isCellRightType, "dequeued cell must be \(cellType)") + } + + func testDequeueNotCrashing() { + let collectionView = createCollectionView() + collectionView.register(cellType, forCellWithReuseIdentifier: cellType.reuseIdentifier) + let _ = collectionView.dequeueReusableCell(for: .init(item: 0, section: 0), cellType: cellType) + } + + private func createCollectionView() -> UICollectionView { + UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout()) + } } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift index fc62647..8c7fd68 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UITableView+extensionsTests.swift @@ -1,29 +1,29 @@ // // UITableView+extensionsTests.swift -// +// // // Created by Sergey Kletsov on 05.04.2022. // import XCTest import UIKit -@testable import UIKitHelper +@testable import UptechUIKitHelper final class UITableViewExtensionsTests: XCTestCase { - private class TestCell: UITableViewCell, ReusableCell { } - private let cellType = TestCell.self - - func testRegisterCorrectType() throws { - let tableView = UITableView() - tableView.register(cellType) - let cell = tableView.dequeueReusableCell(withIdentifier: cellType.reuseIdentifier, for: .init(item: 0, section: 0)) - let isCellRightType = cell.isKind(of: cellType) - XCTAssertTrue(isCellRightType, "dequeued cell must be \(cellType)") - } - - func testDequeueNotCrashing() { - let tableView = UITableView() - tableView.register(cellType, forCellReuseIdentifier: cellType.reuseIdentifier) - let _ = tableView.dequeueReusableCell(for: .init(item: 0, section: 0), cellType: cellType) - } + private class TestCell: UITableViewCell, ReusableCell { } + private let cellType = TestCell.self + + func testRegisterCorrectType() throws { + let tableView = UITableView() + tableView.register(cellType) + let cell = tableView.dequeueReusableCell(withIdentifier: cellType.reuseIdentifier, for: .init(item: 0, section: 0)) + let isCellRightType = cell.isKind(of: cellType) + XCTAssertTrue(isCellRightType, "dequeued cell must be \(cellType)") + } + + func testDequeueNotCrashing() { + let tableView = UITableView() + tableView.register(cellType, forCellReuseIdentifier: cellType.reuseIdentifier) + let _ = tableView.dequeueReusableCell(for: .init(item: 0, section: 0), cellType: cellType) + } } diff --git a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift index 37ee737..4b0c091 100644 --- a/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift +++ b/Tests/Uptech-iOS-Helpers-Tests/UIKitHelper/UIView+extensionsTests.swift @@ -1,74 +1,74 @@ // // UIView+extensionsTests.swift -// +// // // Created by Sergey Kletsov on 29.03.2022. // import XCTest -@testable import UIKitHelper +@testable import UptechUIKitHelper final class UIViewExtensionsTests: XCTestCase { - - func testSubviewAdding() throws { - let view = UIView() - let sut = UIView() - let constrains = [sut.heightAnchor.constraint(equalToConstant: 10), - sut.widthAnchor.constraint(equalTo: view.widthAnchor), - sut.centerYAnchor.constraint(equalTo: view.centerYAnchor)] - - view.addSubview(sut, withConstraints: constrains) - - XCTAssertTrue(view.subviews.contains(sut), "view should contain sut") - XCTAssertFalse(sut.translatesAutoresizingMaskIntoConstraints, "sut's translatesAutoresizingMaskIntoConstraints should be false") - XCTAssertTrue(constrains.allSatisfy(\.isActive), "all constrains should be active") - } - - func testSubviewWithEdgeConstraintsAdding() throws { - let frame = CGRect(origin: .zero, size: .init(width: 10, height: 10)) - let view = UIView(frame: frame) - let sut = UIView() - - view.addSubviewWithEdgeConstraints(sut) - sut.layoutIfNeeded() - - XCTAssertEqual(frame, sut.bounds, "sut's bounds should be equal to view's bounds") - } - - func testSubviewInserting() throws { - let view = UIView() - let subview1 = UIView() - let subview2 = UIView() - view.addSubview(subview1) - view.addSubview(subview2) - - let sut = UIView() - let constrains = [sut.heightAnchor.constraint(equalToConstant: 10), - sut.widthAnchor.constraint(equalTo: view.widthAnchor), - sut.centerYAnchor.constraint(equalTo: view.centerYAnchor)] - let index = 1 - view.insertSubview(sut, at: index, withConstraints: constrains) - - XCTAssertEqual(view.subviews.firstIndex(of: sut), index, "sut's index should be \(index)") - XCTAssertFalse(sut.translatesAutoresizingMaskIntoConstraints, "sut's translatesAutoresizingMaskIntoConstraints should be false") - XCTAssertTrue(constrains.allSatisfy(\.isActive), "all constrains should be active") - } - - func testSubviewWithEdgeConstraintsInserting() throws { - let frame = CGRect(origin: .zero, size: .init(width: 10, height: 10)) - let view = UIView(frame: frame) - let subview1 = UIView() - let subview2 = UIView() - view.addSubview(subview1) - view.addSubview(subview2) - - let sut = UIView() - let index = 1 - view.insertSubviewWithEdgeConstraints(sut, at: index) - sut.layoutIfNeeded() - - XCTAssertEqual(view.subviews.firstIndex(of: sut), index, "sut's index should be \(index)") - XCTAssertEqual(frame, sut.bounds, "sut's bounds should be equal to view's bounds") - } + + func testSubviewAdding() throws { + let view = UIView() + let sut = UIView() + let constrains = [sut.heightAnchor.constraint(equalToConstant: 10), + sut.widthAnchor.constraint(equalTo: view.widthAnchor), + sut.centerYAnchor.constraint(equalTo: view.centerYAnchor)] + + view.addSubview(sut, withConstraints: constrains) + + XCTAssertTrue(view.subviews.contains(sut), "view should contain sut") + XCTAssertFalse(sut.translatesAutoresizingMaskIntoConstraints, "sut's translatesAutoresizingMaskIntoConstraints should be false") + XCTAssertTrue(constrains.allSatisfy(\.isActive), "all constrains should be active") + } + + func testSubviewWithEdgeConstraintsAdding() throws { + let frame = CGRect(origin: .zero, size: .init(width: 10, height: 10)) + let view = UIView(frame: frame) + let sut = UIView() + + view.addSubviewWithEdgeConstraints(sut) + sut.layoutIfNeeded() + + XCTAssertEqual(frame, sut.bounds, "sut's bounds should be equal to view's bounds") + } + + func testSubviewInserting() throws { + let view = UIView() + let subview1 = UIView() + let subview2 = UIView() + view.addSubview(subview1) + view.addSubview(subview2) + + let sut = UIView() + let constrains = [sut.heightAnchor.constraint(equalToConstant: 10), + sut.widthAnchor.constraint(equalTo: view.widthAnchor), + sut.centerYAnchor.constraint(equalTo: view.centerYAnchor)] + let index = 1 + view.insertSubview(sut, at: index, withConstraints: constrains) + + XCTAssertEqual(view.subviews.firstIndex(of: sut), index, "sut's index should be \(index)") + XCTAssertFalse(sut.translatesAutoresizingMaskIntoConstraints, "sut's translatesAutoresizingMaskIntoConstraints should be false") + XCTAssertTrue(constrains.allSatisfy(\.isActive), "all constrains should be active") + } + + func testSubviewWithEdgeConstraintsInserting() throws { + let frame = CGRect(origin: .zero, size: .init(width: 10, height: 10)) + let view = UIView(frame: frame) + let subview1 = UIView() + let subview2 = UIView() + view.addSubview(subview1) + view.addSubview(subview2) + + let sut = UIView() + let index = 1 + view.insertSubviewWithEdgeConstraints(sut, at: index) + sut.layoutIfNeeded() + + XCTAssertEqual(view.subviews.firstIndex(of: sut), index, "sut's index should be \(index)") + XCTAssertEqual(frame, sut.bounds, "sut's bounds should be equal to view's bounds") + } } From e960f7d9afd9f1dfc9fcf2b1da9a5eda8ea998be Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Fri, 2 Aug 2024 18:17:54 +0300 Subject: [PATCH 04/10] added SwiftUI target updated run tests workflow --- .github/workflows/run_tests.yml | 7 +-- Package.swift | 4 +- .../SwiftUIHelper/View+GeometryReader.swift | 62 +++++++++++++++++++ .../View+conditionalModifier.swift | 44 +++++++++++++ .../SwiftUIHelper/View+customOnChange.swift | 24 +++++++ 5 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 195abca..f0e7b99 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -1,9 +1,8 @@ name: Tests on: - push: - branches-ignore: - - master + pull_request: + types: [opened, synchronize] jobs: run_tests: @@ -12,4 +11,4 @@ jobs: - name: Prepare branch on runner uses: actions/checkout@v3 - name: Build & Test - run: xcodebuild build clean test -scheme "Uptech-iOS-Helpers" -destination "platform=iOS Simulator,name=IPhone 11" + run: xcodebuild build clean test -scheme "Uptech Helpers" -destination "platform=iOS Simulator,name=IPhone 11" diff --git a/Package.swift b/Package.swift index 44cef8b..82fd49c 100644 --- a/Package.swift +++ b/Package.swift @@ -7,11 +7,13 @@ let package = Package( platforms: [.iOS(.v13)], products: [ .library(name: "UptechFoundationHelper", targets: ["UptechFoundationHelper"]), - .library(name: "UptechUIKitHelper", targets: ["UptechUIKitHelper"]) + .library(name: "UptechUIKitHelper", targets: ["UptechUIKitHelper"]), + .library(name: "UptechSwiftUIHelper", targets: ["UptechSwiftUIHelper"]) ], targets: [ .target(name: "UptechFoundationHelper", path: "Sources/Uptech-iOS-Helpers/FoundationHelper"), .target(name: "UptechUIKitHelper", path: "Sources/Uptech-iOS-Helpers/UIKitHelper"), + .target(name: "UptechSwiftUIHelper", path: "Sources/Uptech-iOS-Helpers/SwiftUIHelper"), .testTarget(name: "FoundationHelper-Test", dependencies: ["UptechFoundationHelper"], path: "Tests/Uptech-iOS-Helpers-Tests/FoundationHelper"), diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift new file mode 100644 index 0000000..9bec9e7 --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift @@ -0,0 +1,62 @@ +// +// View+GeometryReader.swift +// +// +// Created by Sergey Kletsov on 02.08.2024. +// + +import SwiftUI + +private struct SizePreferenceKey: PreferenceKey { + static var defaultValue: CGSize = .zero + + static func reduce(value: inout CGSize, nextValue: () -> CGSize) {} +} + +private struct GlobalFramePreferenceKey: PreferenceKey { + static var defaultValue: CGRect = .zero + + static func reduce(value: inout CGRect, nextValue: () -> CGRect) {} +} + +public extension View { + func readSize(onChange: @escaping (CGSize) -> Void) -> some View { + background( + GeometryReader { geometryProxy in + Color.clear + .preference(key: SizePreferenceKey.self, value: geometryProxy.size) + } + ) + .onPreferenceChange(SizePreferenceKey.self, perform: onChange) + } + + func readFrame(coordinateSpace: CoordinateSpace, onChange: @escaping (CGRect) -> Void) -> some View { + background( + GeometryReader { geometryProxy in + Color.clear + .preference(key: GlobalFramePreferenceKey.self, value: geometryProxy.frame(in: coordinateSpace)) + } + ) + .onPreferenceChange(GlobalFramePreferenceKey.self, perform: onChange) + } + + func readGlobalFrame(onChange: @escaping (CGRect) -> Void) -> some View { + readFrame(coordinateSpace: .global, onChange: onChange) + } + + func readOffset(onChange: @escaping (CGPoint) -> Void) -> some View { + readFrame(coordinateSpace: .global) { frame in + onChange(frame.origin) + } + } + + func readInsets(_ closure: @escaping (EdgeInsets) -> Void) -> some View { + GeometryReader { geometryProxy in + self.onAppear { + DispatchQueue.main.async { + closure(geometryProxy.safeAreaInsets) + } + } + } + } +} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift new file mode 100644 index 0000000..d6618c4 --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift @@ -0,0 +1,44 @@ +// +// View+conditionalModifier.swift +// +// +// Created by Sergey Kletsov on 02.08.2024. +// + +import SwiftUI + +public extension View { + typealias ContentTransform = (Self) -> Content + + @ViewBuilder + func conditionalModifier( + _ condition: @autoclosure () -> Bool, + ifTrue: ContentTransform, + else ifFalse: ContentTransform + ) -> some View { + if condition() { + ifTrue(self) + } else { + ifFalse(self) + } + } + + @ViewBuilder + func `if`( + _ condition: @autoclosure () -> Bool, + transform: ContentTransform + ) -> some View { + conditionalModifier( + condition(), + ifTrue: transform, + else: { $0 } + ) + } + + @ViewBuilder + func modify( + @ViewBuilder content: ContentTransform + ) -> some View { + content(self) + } +} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift new file mode 100644 index 0000000..430693d --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift @@ -0,0 +1,24 @@ +// +// View+customOnChange.swift +// +// +// Created by Sergey Kletsov on 02.08.2024. +// + +import SwiftUI + +public extension View { + @available(iOS 14.0, *) + @ViewBuilder + func customOnChange( + of value: V, + initial: Bool = false, + _ action: @escaping (V) -> Void + ) -> some View where V: Equatable { + if #available(iOS 17.0, *) { + self.onChange(of: value, initial: initial, { _, newValue in action(newValue) }) + } else { + self.onChange(of: value, perform: action) + } + } +} From 13fe72b31ac59b10f9c052aeb8264f97abf0fe6a Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Wed, 7 Aug 2024 17:22:46 +0300 Subject: [PATCH 05/10] added legacy library --- Package.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Package.swift b/Package.swift index 82fd49c..f0a2f7b 100644 --- a/Package.swift +++ b/Package.swift @@ -6,6 +6,7 @@ let package = Package( name: "Uptech-iOS-Helpers", platforms: [.iOS(.v13)], products: [ + .library(name: "Uptech-iOS-Helpers", targets: ["UptechFoundationHelper", "UptechUIKitHelper", "UptechSwiftUIHelper"]), .library(name: "UptechFoundationHelper", targets: ["UptechFoundationHelper"]), .library(name: "UptechUIKitHelper", targets: ["UptechUIKitHelper"]), .library(name: "UptechSwiftUIHelper", targets: ["UptechSwiftUIHelper"]) From 861b6e1572e37b5ff2e4b3a5d408ce46cae02965 Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Wed, 7 Aug 2024 19:02:12 +0300 Subject: [PATCH 06/10] added ProportionalHStack added ProportionalVStack added documentation to all SwiftUI helpers updated SwiftUI folders structure --- .../View+GeometryReader.swift | 25 +++++-- .../Extensions/View+conditionalModifier.swift | 65 +++++++++++++++++++ .../Extensions/View+customOnChange.swift | 31 +++++++++ .../Layouts/ProportionalHStack.swift | 56 ++++++++++++++++ .../Layouts/ProportionalVStack.swift | 56 ++++++++++++++++ .../View+conditionalModifier.swift | 44 ------------- .../SwiftUIHelper/View+customOnChange.swift | 24 ------- 7 files changed, 229 insertions(+), 72 deletions(-) rename Sources/Uptech-iOS-Helpers/SwiftUIHelper/{ => Extensions}/View+GeometryReader.swift (57%) create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+conditionalModifier.swift create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+customOnChange.swift create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalHStack.swift create mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalVStack.swift delete mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift delete mode 100644 Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+GeometryReader.swift similarity index 57% rename from Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift rename to Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+GeometryReader.swift index 9bec9e7..921f9f4 100644 --- a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+GeometryReader.swift +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+GeometryReader.swift @@ -20,6 +20,9 @@ private struct GlobalFramePreferenceKey: PreferenceKey { } public extension View { + /// Modifier to read view size. Uses GeometryReader + /// - Parameter onChange: A closure to run when size changes + /// - Returns: A view that calls onChange closure when the view size changes. func readSize(onChange: @escaping (CGSize) -> Void) -> some View { background( GeometryReader { geometryProxy in @@ -29,7 +32,12 @@ public extension View { ) .onPreferenceChange(SizePreferenceKey.self, perform: onChange) } - + + /// Modifier to read view frame. Uses GeometryReader + /// - Parameters: + /// - coordinateSpace: Coordinate space to get frame + /// - onChange: A closure to run when frame changes + /// - Returns: A view that calls onChange closure when the view frame changes in given coordinate space. func readFrame(coordinateSpace: CoordinateSpace, onChange: @escaping (CGRect) -> Void) -> some View { background( GeometryReader { geometryProxy in @@ -39,17 +47,26 @@ public extension View { ) .onPreferenceChange(GlobalFramePreferenceKey.self, perform: onChange) } - + + /// Modifier to read view frame in global coordinate space. Uses GeometryReader + /// - onChange: A closure to run when frame changes + /// - Returns: A view that calls onChange closure when the view frame changes in global coordinate space. func readGlobalFrame(onChange: @escaping (CGRect) -> Void) -> some View { readFrame(coordinateSpace: .global, onChange: onChange) } - + + /// Modifier to read view origin in global coordinate space. Uses GeometryReader + /// - onChange: A closure to run when frame's origin changes + /// - Returns: A view that calls onChange closure when the view frame's origin changes in global coordinate space. func readOffset(onChange: @escaping (CGPoint) -> Void) -> some View { readFrame(coordinateSpace: .global) { frame in onChange(frame.origin) } } - + + /// Modifier to read view safeAreaInsets. Embeds view inside GeometryReader + /// - Parameter closure: A closure to run when view safeAreaInsets are configured (after view appeared) + /// - Returns: GeometryReader that contains view and calls closure after view is appeared with calculated safeAreaInsets func readInsets(_ closure: @escaping (EdgeInsets) -> Void) -> some View { GeometryReader { geometryProxy in self.onAppear { diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+conditionalModifier.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+conditionalModifier.swift new file mode 100644 index 0000000..60914b7 --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+conditionalModifier.swift @@ -0,0 +1,65 @@ +// +// View+conditionalModifier.swift +// +// +// Created by Sergey Kletsov on 02.08.2024. +// + +import SwiftUI + +public extension View { + typealias ContentTransform = (Self) -> Content + + /// Conditional Modifier method that modifies view depending of input Bool + /// - Parameters: + /// - condition: Bool condition to check + /// - ifTrue: Modifier closure that will be applied if condition is true + /// - ifFalse: Modifier closure that will be applied if condition is false + /// - Returns: Self modified by ifTrue or ifFalse closure + @ViewBuilder + func conditionalModifier( + _ condition: @autoclosure () -> Bool, + ifTrue: ContentTransform, + else ifFalse: ContentTransform + ) -> some View { + if condition() { + ifTrue(self) + } else { + ifFalse(self) + } + } + + /// Conditional Modifier method that modifies view depending of input Bool + /// - Parameters: + /// - condition: Bool condition to check + /// - ifTrue: Modifier closure that will be applied if condition is true + /// - ifFalse: Modifier closure that will be applied if condition is false + /// - Returns: Self modified by ifTrue or ifFalse closure + + /// Conditional Modifier method that modifies view depending of input Bool + /// - Parameters: + /// - condition: Bool condition to check + /// - transform: Modifier closure that will be applied if condition is true + /// - Returns: Self modified by ifTrue closure if condition is true, Self otherwise + @ViewBuilder + func `if`( + _ condition: @autoclosure () -> Bool, + transform: ContentTransform + ) -> some View { + conditionalModifier( + condition(), + ifTrue: transform, + else: { $0 } + ) + } + + /// Modifier method that modifies view + /// - Parameter transform: Modifier closure to apply + /// - Returns: Self modified by transform closure + @ViewBuilder + func modify( + @ViewBuilder transform: ContentTransform + ) -> some View { + transform(self) + } +} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+customOnChange.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+customOnChange.swift new file mode 100644 index 0000000..1f94722 --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Extensions/View+customOnChange.swift @@ -0,0 +1,31 @@ +// +// View+customOnChange.swift +// +// +// Created by Sergey Kletsov on 02.08.2024. +// + +import SwiftUI + +public extension View { + /// Adds a modifier for this view that fires an action when a specific value changes. + /// Calls different methods depending of iOS version (new system onChange modifier was introduced in iOS 17) + /// - Parameters: + /// - value: The value to check against when determining whether to run the closure. + /// - initial: Whether the action should be run when this view initially appears. (will be used only on iOS 17) + /// - action: A closure to run when the value changes. Will use newValue on iOS 17 + /// - Returns: A view that fires an action when the specified value changes. + @available(iOS 14.0, *) + @ViewBuilder + func customOnChange( + of value: V, + initial: Bool = false, + _ action: @escaping (V) -> Void + ) -> some View where V: Equatable { + if #available(iOS 17.0, *) { + self.onChange(of: value, initial: initial, { _, newValue in action(newValue) }) + } else { + self.onChange(of: value, perform: action) + } + } +} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalHStack.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalHStack.swift new file mode 100644 index 0000000..033b9ea --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalHStack.swift @@ -0,0 +1,56 @@ +// +// ProportionalHStack.swift +// +// +// Created by Sergey Kletsov on 07.08.2024. +// + +import SwiftUI + +/// HStack layout that layouts subviews by given proportions +@available(iOS 16.0, *) +struct ProportionalHStack: Layout { + let proportions: [CGFloat] + let spacing: CGFloat + + /// Creates new layout with given proportions and spacing + /// - Parameters: + /// - proportions: Array of proportions. Numbers in array should add up to **1.0**. Number of proportions should be equal to number of subviews. + /// - spacing: Spacing between subviews. Default value is 0 + init(proportions: [CGFloat], spacing: CGFloat = 0) { + self.proportions = proportions + self.spacing = spacing + } + + func sizeThatFits( + proposal: ProposedViewSize, + subviews: Subviews, + cache: inout Void + ) -> CGSize { + proposal.replacingUnspecifiedDimensions() + } + + func placeSubviews( + in bounds: CGRect, + proposal: ProposedViewSize, + subviews: Subviews, + cache: inout Void + ) { + guard subviews.count == proportions.count else { + return + } + + let totalWidth = bounds.width - (spacing * CGFloat(subviews.count - 1)) + var xOffset: CGFloat = bounds.minX + + for (index, subview) in subviews.enumerated() { + let width = totalWidth * proportions[index] + subview.place( + at: CGPoint(x: xOffset, y: bounds.midY), + anchor: .leading, + proposal: ProposedViewSize(width: width, height: bounds.height) + ) + xOffset += width + spacing + } + } +} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalVStack.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalVStack.swift new file mode 100644 index 0000000..de9a991 --- /dev/null +++ b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/Layouts/ProportionalVStack.swift @@ -0,0 +1,56 @@ +// +// ProportionalVStack.swift +// +// +// Created by Sergey Kletsov on 07.08.2024. +// + +import SwiftUI + +/// VStack layout that layouts subviews by given proportions +@available(iOS 16.0, *) +public struct ProportionalVStack: Layout { + private let proportions: [CGFloat] + private let spacing: CGFloat + + /// Creates new layout with given proportions and spacing + /// - Parameters: + /// - proportions: Array of proportions. Numbers in array should add up to **1.0**. Number of proportions should be equal to number of subviews. + /// - spacing: Spacing between subviews. Default value is 0 + init(proportions: [CGFloat], spacing: CGFloat = 0) { + self.proportions = proportions + self.spacing = spacing + } + + public func sizeThatFits( + proposal: ProposedViewSize, + subviews: Subviews, + cache: inout Void + ) -> CGSize { + proposal.replacingUnspecifiedDimensions() + } + + public func placeSubviews( + in bounds: CGRect, + proposal: ProposedViewSize, + subviews: Subviews, + cache: inout Void + ) { + guard subviews.count == proportions.count else { + return + } + + let totalHeight = bounds.height - (spacing * CGFloat(subviews.count - 1)) + var yOffset: CGFloat = bounds.minY + + for (index, subview) in subviews.enumerated() { + let height = totalHeight * proportions[index] + subview.place( + at: CGPoint(x: bounds.midX, y: yOffset), + anchor: .top, + proposal: ProposedViewSize(width: bounds.width, height: height) + ) + yOffset += height + spacing + } + } +} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift deleted file mode 100644 index d6618c4..0000000 --- a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+conditionalModifier.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// View+conditionalModifier.swift -// -// -// Created by Sergey Kletsov on 02.08.2024. -// - -import SwiftUI - -public extension View { - typealias ContentTransform = (Self) -> Content - - @ViewBuilder - func conditionalModifier( - _ condition: @autoclosure () -> Bool, - ifTrue: ContentTransform, - else ifFalse: ContentTransform - ) -> some View { - if condition() { - ifTrue(self) - } else { - ifFalse(self) - } - } - - @ViewBuilder - func `if`( - _ condition: @autoclosure () -> Bool, - transform: ContentTransform - ) -> some View { - conditionalModifier( - condition(), - ifTrue: transform, - else: { $0 } - ) - } - - @ViewBuilder - func modify( - @ViewBuilder content: ContentTransform - ) -> some View { - content(self) - } -} diff --git a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift b/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift deleted file mode 100644 index 430693d..0000000 --- a/Sources/Uptech-iOS-Helpers/SwiftUIHelper/View+customOnChange.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// View+customOnChange.swift -// -// -// Created by Sergey Kletsov on 02.08.2024. -// - -import SwiftUI - -public extension View { - @available(iOS 14.0, *) - @ViewBuilder - func customOnChange( - of value: V, - initial: Bool = false, - _ action: @escaping (V) -> Void - ) -> some View where V: Equatable { - if #available(iOS 17.0, *) { - self.onChange(of: value, initial: initial, { _, newValue in action(newValue) }) - } else { - self.onChange(of: value, perform: action) - } - } -} From 17e801634cb48f476b5433c546dfc4f59487c435 Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Thu, 8 Aug 2024 14:31:48 +0300 Subject: [PATCH 07/10] updated podspec --- Uptech_iOS_Helpers.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Uptech_iOS_Helpers.podspec b/Uptech_iOS_Helpers.podspec index b4406b5..085479c 100644 --- a/Uptech_iOS_Helpers.podspec +++ b/Uptech_iOS_Helpers.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'Uptech_iOS_Helpers' - s.version = '1.0.1' + s.version = '2.0.0' s.summary = 'iOS helper library that contains commonly used code in Uptech iOS projects.' s.homepage = 'https://github.com/uptechteam/Uptech-iOS-Helpers' s.license = { :type => 'MIT', :file => 'LICENSE.md' } s.author = { 'Sergey Kletsov' => 'sergey.kletsov@uptech.team' } s.source = { :git => 'https://github.com/uptechteam/Uptech-iOS-Helpers.git', :tag => s.version.to_s } - s.ios.deployment_target = '11.0' + s.ios.deployment_target = '13.0' s.swift_version = '5.5' s.source_files = 'Sources/Uptech-iOS-Helpers/**/*' end From 3bd8863fc75077d783031c8f3112d34620bb6db4 Mon Sep 17 00:00:00 2001 From: Serhii Klietsov Date: Thu, 8 Aug 2024 15:09:13 +0300 Subject: [PATCH 08/10] Update README.md --- README.md | 90 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index b84d0fe..bfb900b 100644 --- a/README.md +++ b/README.md @@ -5,41 +5,79 @@ iOS helper library that contains commonly used code in **Uptech** iOS projects. ## What's included -- Protocols - - **ReusableCell** - - Protocol that helps with reusable cells. +
+ + 🔧 Foundation Helpers + + + - Array extensions + - safe subscript + - next, previous, remove *Element* methods + + - Collection: + - subscript by indexPath + +
+ +
+  + 🖼️ UIKit Helpers + + + - Protocols + - **ReusableCell** + + Protocol that helps with reusable cells. + + If used on UITableViewCell subclasses provides handy methods for registering and dequeueing cells in UITableView's - If used on UITableViewCell subclasses provides handy methods for registering and dequeueing cells in UITableView's - - - **NibInitializable** - - Protocol that helps to initialize view with xib. -- Table & Collection View helpers - - *dequeue* and *register* methods for cells that confirm's to **ReusableCell** and optionally **NibInitializable** (for cell's created via xibs) -- UI-in-code helpers - - UIView extensions: - - subview adding, insertions *with* constrains - - corner radius - - NSLayoutConstraint: - - priority changing method - - constraint activation method for array of constrains - - UILayoutPriority: - - frequently used values -- Array extensions - - safe subscript - - next, previous, remove *Element* methods -- Collection: - - subscript by indexPath + - **NibInitializable** + + Protocol that helps to initialize view with xib. + - Table & Collection View helpers + - *dequeue* and *register* methods for cells that confirm's to **ReusableCell** and optionally **NibInitializable** (for cell's created via xibs) + - UI-in-code helpers + - UIView extensions: + - subview adding, insertions *with* constrains + - corner radius + - NSLayoutConstraint: + - priority changing method + - constraint activation method for array of constrains + - UILayoutPriority: + - frequently used values + +
+ +
+ + 🕊️ SwiftUI helpers + + + - Layouts + - ProportionalHStack and ProportionalVStack + - Layouts that resizes views with given proportions + + - View extensions + - conditionalModifiers (if, if/else), regular modifier + - customOnChange + - size/frame/offset/safeAreaInsets readers + +
## Installation #### Swift Package Manager *Note: Instructions below are for using SwiftPM without the Xcode UI. It's the easiest to go to your Project Settings -> Swift Packages and add Package from there using link https://github.com/uptechteam/Uptech-iOS-Helpers.git* +Package contains 4 libraries: +- UptechFoundationHelper +- UptechUIKitHelper +- UptechSwiftUIHelper +- Uptech-iOS-Helpers (first 3 combined) + To integrate using Apple's Swift package manager, without Xcode integration, add the following as a dependency to your Package.swift: ```swift -.package(url: "https://github.com/uptechteam/Uptech-iOS-Helpers.git", .upToNextMajor(from: "1.0.0")) +.package(url: "https://github.com/uptechteam/Uptech-iOS-Helpers.git", .upToNextMajor(from: "2.0.0")) ``` #### CocoaPods From b1f6c41dfdfb8ce8facf1dbf9f6874a3fe776452 Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Thu, 8 Aug 2024 15:37:44 +0300 Subject: [PATCH 09/10] fix run_tests attempt 1 --- .github/workflows/run_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index f0e7b99..895391c 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -11,4 +11,4 @@ jobs: - name: Prepare branch on runner uses: actions/checkout@v3 - name: Build & Test - run: xcodebuild build clean test -scheme "Uptech Helpers" -destination "platform=iOS Simulator,name=IPhone 11" + run: xcodebuild build clean test -scheme "Uptech-iOS-Helpers-Package" -destination "platform=iOS Simulator,name=IPhone 11" From 643b3eb35569b36d4ca32604016b7341dc55de6a Mon Sep 17 00:00:00 2001 From: Sergey Kletsov Date: Thu, 8 Aug 2024 15:40:26 +0300 Subject: [PATCH 10/10] fix run_tests attempt 2 --- .github/workflows/run_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 895391c..55bb603 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -11,4 +11,4 @@ jobs: - name: Prepare branch on runner uses: actions/checkout@v3 - name: Build & Test - run: xcodebuild build clean test -scheme "Uptech-iOS-Helpers-Package" -destination "platform=iOS Simulator,name=IPhone 11" + run: xcodebuild build clean test -scheme "Uptech-iOS-Helpers-Package" -destination "platform=iOS Simulator,name=IPhone 15"