From 6c8df368913a6bce585491b8eaf7159b3215df2c Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 10:42:05 +0200 Subject: [PATCH 01/24] update flow layout section controller --- SectionKit.xcodeproj/project.pbxproj | 16 ++---- .../BaseFlowLayoutSectionController.swift | 48 ++++++++++++++++++ ...undationDiffingListSectionController.swift | 0 .../ListSectionController.swift | 2 +- .../SingleItemSectionController.swift | 2 +- .../SingleModelSectionController.swift | 2 +- .../Generic/BaseSectionController.swift | 50 ++----------------- .../SectionController/SectionController.swift | 11 ++-- 8 files changed, 63 insertions(+), 68 deletions(-) create mode 100644 SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift rename SectionKit/Sources/SectionController/{Generic => FlowLayout}/FoundationDiffingListSectionController.swift (100%) rename SectionKit/Sources/SectionController/{Generic => FlowLayout}/ListSectionController.swift (97%) rename SectionKit/Sources/SectionController/{Generic => FlowLayout}/SingleItemSectionController.swift (98%) rename SectionKit/Sources/SectionController/{Generic => FlowLayout}/SingleModelSectionController.swift (96%) diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index c4e95594..94ecdde1 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -468,6 +468,7 @@ 5AA9D95126AAA5E000679D88 /* MockCollectionViewCell.swift */, 5A8D3E5327E8D0E200073712 /* MockCollectionViewContext.swift */, 5AA9D95526AAA61700679D88 /* MockErrorHandler.swift */, + D91425802BBBF8670005E8CD /* MockFlowLayoutSectionController.swift */, 5A0B776F26B19EB300B054D4 /* MockListCollectionViewAdapterDataSource.swift */, 5A0B775326AFF4D500B054D4 /* MockScrollViewDelegate.swift */, 5AB6644A26A86F7A004DC230 /* MockSectionController.swift */, @@ -544,8 +545,9 @@ 5AE175A92667DA3E00D4DCE1 /* SectionController */ = { isa = PBXGroup; children = ( + D9CCE9B62BADF2FD00EED204 /* Generic */, + D9CCE9B22BADED3D00EED204 /* FlowLayout */, 5AE175AD2667DA3E00D4DCE1 /* Update */, - 5AE175B42667DA3E00D4DCE1 /* Generic */, 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */, 5AE175BA2667DA3F00D4DCE1 /* SectionController.swift */, 5AE175AB2667DA3E00D4DCE1 /* SectionDataSource.swift */, @@ -568,18 +570,6 @@ path = Update; sourceTree = ""; }; - 5AE175B42667DA3E00D4DCE1 /* Generic */ = { - isa = PBXGroup; - children = ( - 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */, - 5AE175B62667DA3E00D4DCE1 /* ListSectionController.swift */, - 5AE175B72667DA3F00D4DCE1 /* SingleItemSectionController.swift */, - 5AE175B82667DA3F00D4DCE1 /* SingleModelSectionController.swift */, - 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift */, - ); - path = Generic; - sourceTree = ""; - }; 5AE175BC2667DA3F00D4DCE1 /* CollectionViewAdapter */ = { isa = PBXGroup; children = ( diff --git a/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift new file mode 100644 index 00000000..c9b6ebe4 --- /dev/null +++ b/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift @@ -0,0 +1,48 @@ +import UIKit + +/// This is a foundational implementation of `FlowLayoutSectionController`, implementing the flow layout delegate while inheriting from the `BaseSectionController`. +@MainActor +open class BaseFlowLayoutSectionController: BaseSectionController, + SectionFlowDelegate, + FlowLayoutSectionController { + open var flowDelegate: SectionFlowDelegate? { self } + + // MARK: - SectionFlowDelegate + + open func sizeForItem( + at indexPath: SectionIndexPath, + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGSize { + (layout as? UICollectionViewFlowLayout)?.itemSize ?? CGSize(width: 50, height: 50) + } + + open func inset(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> UIEdgeInsets { + (layout as? UICollectionViewFlowLayout)?.sectionInset ?? .zero + } + + open func minimumLineSpacing(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> CGFloat { + (layout as? UICollectionViewFlowLayout)?.minimumLineSpacing ?? 10 + } + + open func minimumInteritemSpacing( + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGFloat { + (layout as? UICollectionViewFlowLayout)?.minimumInteritemSpacing ?? 10 + } + + open func referenceSizeForHeader( + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGSize { + (layout as? UICollectionViewFlowLayout)?.headerReferenceSize ?? .zero + } + + open func referenceSizeForFooter( + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGSize { + (layout as? UICollectionViewFlowLayout)?.footerReferenceSize ?? .zero + } +} diff --git a/SectionKit/Sources/SectionController/Generic/FoundationDiffingListSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListSectionController.swift similarity index 100% rename from SectionKit/Sources/SectionController/Generic/FoundationDiffingListSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListSectionController.swift diff --git a/SectionKit/Sources/SectionController/Generic/ListSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/ListSectionController.swift similarity index 97% rename from SectionKit/Sources/SectionController/Generic/ListSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/ListSectionController.swift index cc216a4b..d8d5124c 100644 --- a/SectionKit/Sources/SectionController/Generic/ListSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/ListSectionController.swift @@ -8,7 +8,7 @@ import UIKit of a model to be displayed and the list of items (almost) never changes or should not perform animated updates. */ @MainActor -open class ListSectionController: BaseSectionController { +open class ListSectionController: BaseFlowLayoutSectionController { /** Initialise an instance of `ListSectionController`. diff --git a/SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/SingleItemSectionController.swift similarity index 98% rename from SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/SingleItemSectionController.swift index e003fff9..9f88725d 100644 --- a/SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/SingleItemSectionController.swift @@ -9,7 +9,7 @@ import UIKit - Warning: If `numberOfItems` is overridden, `calculateUpdate(from:to:)` needs to be overridden as well. */ @MainActor -open class SingleItemSectionController: BaseSectionController { +open class SingleItemSectionController: BaseFlowLayoutSectionController { private let areItemsEqual: @MainActor (Item, Item) -> Bool /** diff --git a/SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/SingleModelSectionController.swift similarity index 96% rename from SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/SingleModelSectionController.swift index 143408d1..f2144b49 100644 --- a/SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/SingleModelSectionController.swift @@ -9,7 +9,7 @@ import UIKit it is recommended to use `ListSectionController` instead. */ @MainActor -open class SingleModelSectionController: BaseSectionController { +open class SingleModelSectionController: BaseFlowLayoutSectionController { /** Initialise an instance of `SingleModelSectionController`. diff --git a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift index 7c97544f..bb1b7151 100644 --- a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift @@ -1,16 +1,13 @@ import UIKit -/** - A base implementation of all `SectionController` datasource and delegate protocols. - - Every declaration is marked `open` and can be overridden. - */ +/// This serves as a fundamental `SectionController` implementation, +/// encompassing data source and delegate protocols, with the exception of the flow layout delegate. +/// Each access control is designated as` open`, allowing for easy customization through overrides. @MainActor open class BaseSectionController: SectionController, SectionDataSource, SectionDataSourcePrefetchingDelegate, SectionDelegate, - SectionFlowDelegate, SectionDragDelegate, SectionDropDelegate { // MARK: - Init @@ -28,8 +25,6 @@ open class BaseSectionController: SectionController, open var delegate: SectionDelegate? { self } - open var flowDelegate: SectionFlowDelegate? { self } - @available(iOS 11.0, *) open var dragDelegate: SectionDragDelegate? { self } @@ -263,43 +258,4 @@ open class BaseSectionController: SectionController, ) -> UIDragPreviewParameters? { nil } - - // MARK: - SectionFlowDelegate - - open func sizeForItem( - at indexPath: SectionIndexPath, - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.itemSize ?? CGSize(width: 50, height: 50) - } - - open func inset(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> UIEdgeInsets { - (layout as? UICollectionViewFlowLayout)?.sectionInset ?? .zero - } - - open func minimumLineSpacing(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> CGFloat { - (layout as? UICollectionViewFlowLayout)?.minimumLineSpacing ?? 10 - } - - open func minimumInteritemSpacing( - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGFloat { - (layout as? UICollectionViewFlowLayout)?.minimumInteritemSpacing ?? 10 - } - - open func referenceSizeForHeader( - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.headerReferenceSize ?? .zero - } - - open func referenceSizeForFooter( - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.footerReferenceSize ?? .zero - } } diff --git a/SectionKit/Sources/SectionController/SectionController.swift b/SectionKit/Sources/SectionController/SectionController.swift index 6e155d3b..744c0ade 100644 --- a/SectionKit/Sources/SectionController/SectionController.swift +++ b/SectionKit/Sources/SectionController/SectionController.swift @@ -16,9 +16,6 @@ public protocol SectionController: AnyObject { /// The delegate of this section. var delegate: SectionDelegate? { get } - /// The delegate for the `UICollectionViewFlowLayout` of this section. - var flowDelegate: SectionFlowDelegate? { get } - /// The drag delegate of this section. @available(iOS 11.0, *) var dragDelegate: SectionDragDelegate? { get } @@ -37,11 +34,15 @@ extension SectionController { public var delegate: SectionDelegate? { nil } - public var flowDelegate: SectionFlowDelegate? { nil } - @available(iOS 11.0, *) public var dragDelegate: SectionDragDelegate? { nil } @available(iOS 11.0, *) public var dropDelegate: SectionDropDelegate? { nil } } + +@MainActor +public protocol FlowLayoutSectionController: SectionController { + /// The delegate for the `UICollectionViewFlowLayout` of this section. + var flowDelegate: SectionFlowDelegate? { get } +} From 7bfeea1049df31a4868f8b2445f00d3e42aae9cb Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 10:43:05 +0200 Subject: [PATCH 02/24] add compositional support for the section controller --- ...CompositionalLayoutSectionController.swift | 14 +++ ...CompositionalLayoutSectionController.swift | 115 ++++++++++++++++++ .../SectionController/SectionController.swift | 12 ++ 3 files changed, 141 insertions(+) create mode 100644 SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift create mode 100644 SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift diff --git a/SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift b/SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift new file mode 100644 index 00000000..7c2b5162 --- /dev/null +++ b/SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift @@ -0,0 +1,14 @@ +import UIKit + +/// This is a foundational implementation of `CompositionalLayoutSectionController`, adding the compositional layout section delegate function while inheriting from the `BaseSectionController`. +@MainActor +@available(iOS 13.0, *) +open class BaseCompositionalLayoutSectionController: BaseSectionController, + CompositionalLayoutSectionController { + open func layoutSection( + layoutEnvironment: any NSCollectionLayoutEnvironment + ) -> NSCollectionLayoutSection { + context?.errorHandler.nonCritical(error: .notImplemented()) + return .empty + } +} diff --git a/SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift b/SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift new file mode 100644 index 00000000..fcaf743a --- /dev/null +++ b/SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift @@ -0,0 +1,115 @@ +import UIKit + +/** + A `SectionController` that contains a list of items. Changes to that list will result in a call to + `reloadSections(_:)` on the underlying `UICollectionView`. + + This `SectionController` is typically used when there are multiple semantically similar items + of a model to be displayed and the list of items (almost) never changes or should not perform animated updates. + */ +@MainActor +@available(iOS 13.0, *) +open class ListCompositionalLayoutSectionController: BaseCompositionalLayoutSectionController { + /** + Initialise an instance of `ListSectionController`. + + - Parameter model: The model of this `SectionController`. + */ + public init(model: Model) { + self.model = model + super.init() + if shouldUpdateItems(afterModelChangedTo: model) { + items = items(for: model) + } + } + + override open func didUpdate(model: Any) { + guard let model = model as? Model else { + context?.errorHandler.nonCritical( + error: .sectionControllerModelTypeMismatch( + expected: Model.self, + actual: type(of: model) + ) + ) + return + } + self.model = model + } + + /// The model of this `SectionController`. + open var model: Model { + didSet { + if shouldUpdateItems(afterModelChangedTo: model) { + items = items(for: model) + } + } + } + + /** + Determines if the list of items should be updated after the model was updated to a new value. + + The default value is `true`. + + - Parameter model: The new value of the model. + + - Returns: If the list of items should be updated after the model was updated to a new value. + */ + open func shouldUpdateItems(afterModelChangedTo model: Model) -> Bool { true } + + /** + Derives a list of items from the given `Model`. + + Will be called automatically if `shouldUpdateItems(afterModelChangedTo:)` returned `true`. + + - Parameter model: The new value of the model. + + - Returns: The new items to be displayed in this section. + */ + open func items(for model: Model) -> [Item] { + context?.errorHandler.nonCritical(error: .notImplemented()) + return [] + } + + /** + The list of items currently displayed in the `UICollectionView`. + + Only set this property if `UICollectionView` insertions and deletions are handled, otherwise use `items` instead. + */ + open var collectionViewItems: [Item] = [] + + /// The items of this section. + open var items: [Item] { + get { collectionViewItems } + set { + guard let context = context else { + collectionViewItems = newValue + return + } + if let sectionUpdate = calculateUpdate(from: collectionViewItems, to: newValue) { + context.apply(update: sectionUpdate) + } + } + } + + /** + Calculate the `UICollectionView` events using the difference from the old to the new data. + + - Parameter oldData: The old data currently displayed in the section. + + - Parameter newData: The new data that should be displayed in the section. + + - Returns: The update that should be performed on the section. + */ + open func calculateUpdate( + from oldData: [Item], + to newData: [Item] + ) -> CollectionViewSectionUpdate<[Item]>? { + CollectionViewSectionUpdate( + controller: self, + data: newData, + setData: { self.collectionViewItems = $0 } + ) + } + + override open func numberOfItems(in context: CollectionViewContext) -> Int { items.count } +} diff --git a/SectionKit/Sources/SectionController/SectionController.swift b/SectionKit/Sources/SectionController/SectionController.swift index 744c0ade..78e14e54 100644 --- a/SectionKit/Sources/SectionController/SectionController.swift +++ b/SectionKit/Sources/SectionController/SectionController.swift @@ -46,3 +46,15 @@ public protocol FlowLayoutSectionController: SectionController { /// The delegate for the `UICollectionViewFlowLayout` of this section. var flowDelegate: SectionFlowDelegate? { get } } + +@MainActor +public protocol CompositionalLayoutSectionController: SectionController { + /// Provide the layout section for the Compositional Layout + /// - Parameters: + /// - layoutEnvironment: the environment value for the layout + /// - Returns: The layout for the section + @available(iOS 13.0, *) + func layoutSection( + layoutEnvironment: NSCollectionLayoutEnvironment + ) -> NSCollectionLayoutSection +} From 8fabf99b484015cc17c8541e3875c4d3dac93d54 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 10:43:43 +0200 Subject: [PATCH 03/24] add bridge between layout provider and adapter --- ...istCollectionViewAdapter+Convenience.swift | 4 +- .../ListCollectionViewAdapter.swift | 12 +++++ ...ionCollectionViewAdapter+Convenience.swift | 4 +- .../NSCollectionLayoutSection+Empty.swift | 18 +++++++ .../SectionKitCompositionalLayout.swift | 53 +++++++++++++++++++ 5 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 SectionKit/Sources/Utility/CompositionalLayout/NSCollectionLayoutSection+Empty.swift create mode 100644 SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift diff --git a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift index d98d0429..9b1f82ab 100644 --- a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift @@ -58,12 +58,12 @@ extension ListCollectionViewAdapter { extension ListCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { - controller(at: indexPath)?.flowDelegate + (controller(at: indexPath) as? FlowLayoutSectionController)?.flowDelegate } @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { - controller(at: index)?.flowDelegate + (controller(at: index) as? FlowLayoutSectionController)?.flowDelegate } } diff --git a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter.swift b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter.swift index ee54431c..d86535c2 100644 --- a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter.swift +++ b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter.swift @@ -49,6 +49,12 @@ open class ListCollectionViewAdapter: NSObject, CollectionViewAdapter { collectionView.dragDelegate = self collectionView.dropDelegate = self } + if #available(iOS 13.0, *), + let layout = collectionView.collectionViewLayout as? SectionKitCompositionalLayout { + layout.sections = { [weak self] in + self?.collectionViewSections ?? [] + } + } } /** @@ -90,6 +96,12 @@ open class ListCollectionViewAdapter: NSObject, CollectionViewAdapter { collectionView.dragDelegate = self collectionView.dropDelegate = self } + if #available(iOS 13.0, *), + let layout = collectionView.collectionViewLayout as? SectionKitCompositionalLayout { + layout.sections = { [weak self] in + self?.collectionViewSections ?? [] + } + } } public let context: CollectionViewContext diff --git a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift index e27e473f..4fb424e7 100644 --- a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift @@ -58,12 +58,12 @@ extension SingleSectionCollectionViewAdapter { extension SingleSectionCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { - controller(at: indexPath)?.flowDelegate + (controller(at: indexPath) as? FlowLayoutSectionController)?.flowDelegate } @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { - controller(at: index)?.flowDelegate + (controller(at: index) as? FlowLayoutSectionController)?.flowDelegate } } diff --git a/SectionKit/Sources/Utility/CompositionalLayout/NSCollectionLayoutSection+Empty.swift b/SectionKit/Sources/Utility/CompositionalLayout/NSCollectionLayoutSection+Empty.swift new file mode 100644 index 00000000..39e68e45 --- /dev/null +++ b/SectionKit/Sources/Utility/CompositionalLayout/NSCollectionLayoutSection+Empty.swift @@ -0,0 +1,18 @@ +import UIKit + +@available(iOS 13.0, *) +extension NSCollectionLayoutSection { + static let empty: NSCollectionLayoutSection = { + let layoutSize = NSCollectionLayoutSize( + widthDimension: .absolute(0), + heightDimension: .absolute(0) + ) + return NSCollectionLayoutSection( + group: .vertical( + layoutSize: layoutSize, + subitem: .init(layoutSize: layoutSize), + count: 1 + ) + ) + }() +} diff --git a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift new file mode 100644 index 00000000..b033cccf --- /dev/null +++ b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift @@ -0,0 +1,53 @@ +import UIKit + +/// This compositional layout is designed for the section kit. +/// It ensures that the layout provider utilizes the layout section provided by the compositional layout section controller. +@MainActor +@available(iOS 13.0, *) +final public class SectionKitCompositionalLayout: UICollectionViewCompositionalLayout { + // Use internally to bridge the sections from the adapter to the section provider. + var sections: (() -> [Section])? + + public init() { + var sections: (() -> [Section])? + super.init { index, environment in + guard let sections = sections?() else { + assertionFailure("The section provider doesn't set up correctly, please use the `CollectionViewCompositionalLayoutAdapter`") + return .empty + } + guard sections.count > index else { + assertionFailure("Section index out of bound") + return .empty + } + guard let compositionalLayoutSectionController = sections[index].controller + as? BaseCompositionalLayoutSectionController else { + assertionFailure("Please use the `CompositionalLayoutSectionControler`") + return .empty + } + return compositionalLayoutSectionController.layoutSection( + layoutEnvironment: environment + ) + } + sections = { [weak self] in + self?.sections?() ?? [] + } + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @available(*, unavailable) + override init( + sectionProvider: @escaping UICollectionViewCompositionalLayoutSectionProvider, + configuration: UICollectionViewCompositionalLayoutConfiguration + ) { + fatalError("init(sectionProvider:configuration:) has not been implemented") + } + + @available(*, unavailable) + override init(sectionProvider: @escaping UICollectionViewCompositionalLayoutSectionProvider) { + fatalError("init(sectionProvider:) has not been implemented") + } +} From 7df543725d37b7d4021c62b3ba7c98be3dab09f2 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 10:44:10 +0200 Subject: [PATCH 04/24] update tests --- SectionKit.xcodeproj/project.pbxproj | 100 +++++++++++++++--- ...ollectionViewDelegateFlowLayoutTests.swift | 57 ++++++---- ...ollectionViewDelegateFlowLayoutTests.swift | 6 +- ...BaseFlowLayoutSectionControllerTests.swift | 10 ++ .../BaseSectionControllerTests.swift | 5 - ...lDefaultValuesSectionControllerTests.swift | 43 ++++---- ...sitionalLayoutSectionControllerTests.swift | 24 +++++ ...onControllerSectionFlowDelegateTests.swift | 9 ++ ...eFlowLayoutSectionFlowDelegateTests.swift} | 18 +++- ...onControllerSectionFlowDelegateTests.swift | 9 -- ...efaultValuesSectionFlowDelegateTests.swift | 2 +- .../MockFlowLayoutSectionController.swift | 10 ++ .../TestUtilities/MockSectionController.swift | 5 - 13 files changed, 216 insertions(+), 82 deletions(-) create mode 100644 SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift create mode 100644 SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift create mode 100644 SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift rename SectionKit/Tests/SectionController/SectionFlowDelegate/{BaseSectionFlowDelegateTests.swift => BaseFlowLayoutSectionFlowDelegateTests.swift} (96%) delete mode 100644 SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionControllerSectionFlowDelegateTests.swift create mode 100644 SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index 94ecdde1..fdbbd9d8 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -53,8 +53,6 @@ 5A31B8CF26BAE93900036A3F /* BaseSectionDropDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8CE26BAE93900036A3F /* BaseSectionDropDelegateTests.swift */; }; 5A31B8D126BAE94500036A3F /* BaseSectionControllerSectionDropDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8D026BAE94500036A3F /* BaseSectionControllerSectionDropDelegateTests.swift */; }; 5A31B8D326BAE94E00036A3F /* ProtocolDefaultValuesSectionDropDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8D226BAE94E00036A3F /* ProtocolDefaultValuesSectionDropDelegateTests.swift */; }; - 5A31B8D526BAE95700036A3F /* BaseSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8D426BAE95700036A3F /* BaseSectionFlowDelegateTests.swift */; }; - 5A31B8D726BAE96000036A3F /* BaseSectionControllerSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8D626BAE96000036A3F /* BaseSectionControllerSectionFlowDelegateTests.swift */; }; 5A31B8D926BAE96800036A3F /* ProtocolDefaultValuesSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8D826BAE96800036A3F /* ProtocolDefaultValuesSectionFlowDelegateTests.swift */; }; 5A31B8E026BBF32D00036A3F /* UICollectionViewApplyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8DF26BBF32D00036A3F /* UICollectionViewApplyTests.swift */; }; 5A31B8E226BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8E126BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift */; }; @@ -114,13 +112,9 @@ 5AE175FB2667DA3F00D4DCE1 /* CollectionViewUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C52667DA3F00D4DCE1 /* CollectionViewUpdate.swift */; }; 5AE175FC2667DA3F00D4DCE1 /* ListCollectionViewAdapter+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C72667DA3F00D4DCE1 /* ListCollectionViewAdapter+Convenience.swift */; }; 5AE175FD2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDropDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C82667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDropDelegate.swift */; }; - 5AE175FE2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C92667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift */; }; - 5AE175FF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CA2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift */; }; 5AE176002667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegateFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CB2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegateFlowLayout.swift */; }; 5AE176012667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CC2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegate.swift */; }; 5AE176022667DA3F00D4DCE1 /* ListCollectionViewAdapter+UIScrollViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CD2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UIScrollViewDelegate.swift */; }; - 5AE176032667DA3F00D4DCE1 /* ListCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CE2667DA3F00D4DCE1 /* ListCollectionViewAdapter.swift */; }; - 5AE176042667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift */; }; 5AE176052667DA3F00D4DCE1 /* FoundationDiffingListCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175D02667DA3F00D4DCE1 /* FoundationDiffingListCollectionViewAdapter.swift */; }; 5AE176062667DA3F00D4DCE1 /* ListCollectionViewAdapterDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175D12667DA3F00D4DCE1 /* ListCollectionViewAdapterDataSource.swift */; }; 5AE176072667DA3F00D4DCE1 /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175D22667DA3F00D4DCE1 /* Section.swift */; }; @@ -136,6 +130,18 @@ 5AE176112667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175DD2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift */; }; 5AE1761B2667DA7000D4DCE1 /* SectionIndexPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE176132667DA7000D4DCE1 /* SectionIndexPathTests.swift */; }; 5AE1761E2667DA7000D4DCE1 /* SequenceUniqueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE176182667DA7000D4DCE1 /* SequenceUniqueTests.swift */; }; + D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */; }; + D91425692BBBF79E0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */; }; + D914257F2BBBF8310005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */; }; + D91425822BBBF8780005E8CD /* MockFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425802BBBF8670005E8CD /* MockFlowLayoutSectionController.swift */; }; + D91425852BBBFB840005E8CD /* ListCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CE2667DA3F00D4DCE1 /* ListCollectionViewAdapter.swift */; }; + D91425862BBBFB930005E8CD /* BaseFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */; }; + D91425872BBBFBA40005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */; }; + D93269A22BBBFC2400B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CA2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift */; }; + D93269A32BBBFC2700B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C92667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift */; }; + D93269A42BBBFC2B00B33C32 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift */; }; + D9CCE9B52BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */; }; + D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -195,8 +201,6 @@ 5A31B8CE26BAE93900036A3F /* BaseSectionDropDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionDropDelegateTests.swift; sourceTree = ""; }; 5A31B8D026BAE94500036A3F /* BaseSectionControllerSectionDropDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionControllerSectionDropDelegateTests.swift; sourceTree = ""; }; 5A31B8D226BAE94E00036A3F /* ProtocolDefaultValuesSectionDropDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolDefaultValuesSectionDropDelegateTests.swift; sourceTree = ""; }; - 5A31B8D426BAE95700036A3F /* BaseSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionFlowDelegateTests.swift; sourceTree = ""; }; - 5A31B8D626BAE96000036A3F /* BaseSectionControllerSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionControllerSectionFlowDelegateTests.swift; sourceTree = ""; }; 5A31B8D826BAE96800036A3F /* ProtocolDefaultValuesSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolDefaultValuesSectionFlowDelegateTests.swift; sourceTree = ""; }; 5A31B8DF26BBF32D00036A3F /* UICollectionViewApplyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewApplyTests.swift; sourceTree = ""; }; 5A31B8E126BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProtocolDefaultValuesSectionControllerTests.swift; sourceTree = ""; }; @@ -281,6 +285,15 @@ 5AE175DD2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleSectionCollectionViewAdapter.swift; sourceTree = ""; }; 5AE176132667DA7000D4DCE1 /* SectionIndexPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionIndexPathTests.swift; sourceTree = ""; }; 5AE176182667DA7000D4DCE1 /* SequenceUniqueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceUniqueTests.swift; sourceTree = ""; }; + D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCompositionalLayoutSectionController.swift; sourceTree = ""; }; + D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionKitCompositionalLayout.swift; sourceTree = ""; }; + D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseCompositionalLayoutSectionControllerTests.swift; sourceTree = ""; }; + D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionFlowDelegateTests.swift; sourceTree = ""; }; + D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift; sourceTree = ""; }; + D91425802BBBF8670005E8CD /* MockFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockFlowLayoutSectionController.swift; sourceTree = ""; }; + D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCompositionalLayoutSectionController.swift; sourceTree = ""; }; + D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionController.swift; sourceTree = ""; }; + D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSCollectionLayoutSection+Empty.swift"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -403,8 +416,8 @@ 5A31B8B426BAE86700036A3F /* SectionFlowDelegate */ = { isa = PBXGroup; children = ( - 5A31B8D426BAE95700036A3F /* BaseSectionFlowDelegateTests.swift */, - 5A31B8D626BAE96000036A3F /* BaseSectionControllerSectionFlowDelegateTests.swift */, + D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */, + D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */, 5A31B8D826BAE96800036A3F /* ProtocolDefaultValuesSectionFlowDelegateTests.swift */, ); path = SectionFlowDelegate; @@ -531,6 +544,7 @@ 5AE175A12667DA3E00D4DCE1 /* Utility */ = { isa = PBXGroup; children = ( + D9CCE9B92BADF6F600EED204 /* CompositionalLayout */, 5AE175A22667DA3E00D4DCE1 /* Sequence+Unique.swift */, 5AE175A52667DA3E00D4DCE1 /* IndexPath+IsValid.swift */, 5AE175A42667DA3E00D4DCE1 /* Move.swift */, @@ -546,6 +560,7 @@ isa = PBXGroup; children = ( D9CCE9B62BADF2FD00EED204 /* Generic */, + D9CCE9B32BADED5B00EED204 /* CompositionalLayout */, D9CCE9B22BADED3D00EED204 /* FlowLayout */, 5AE175AD2667DA3E00D4DCE1 /* Update */, 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */, @@ -641,6 +656,7 @@ 5AE176122667DA7000D4DCE1 /* SectionController */ = { isa = PBXGroup; children = ( + D91425672BBBF77C0005E8CD /* SectionCompositionalLayout */, 5A31B8AF26BAE81000036A3F /* SectionDataSource */, 5A31B8B026BAE82200036A3F /* SectionDataSourcePrefetchingDelegate */, 5A31B8B126BAE82D00036A3F /* SectionDelegate */, @@ -688,6 +704,52 @@ path = CollectionViewAdapter; sourceTree = ""; }; + D91425672BBBF77C0005E8CD /* SectionCompositionalLayout */ = { + isa = PBXGroup; + children = ( + D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */, + ); + path = SectionCompositionalLayout; + sourceTree = ""; + }; + D9CCE9B22BADED3D00EED204 /* FlowLayout */ = { + isa = PBXGroup; + children = ( + D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */, + 5AE175B62667DA3E00D4DCE1 /* ListSectionController.swift */, + 5AE175B72667DA3F00D4DCE1 /* SingleItemSectionController.swift */, + 5AE175B82667DA3F00D4DCE1 /* SingleModelSectionController.swift */, + 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift */, + ); + path = FlowLayout; + sourceTree = ""; + }; + D9CCE9B32BADED5B00EED204 /* CompositionalLayout */ = { + isa = PBXGroup; + children = ( + D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */, + D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */, + ); + path = CompositionalLayout; + sourceTree = ""; + }; + D9CCE9B62BADF2FD00EED204 /* Generic */ = { + isa = PBXGroup; + children = ( + 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */, + ); + path = Generic; + sourceTree = ""; + }; + D9CCE9B92BADF6F600EED204 /* CompositionalLayout */ = { + isa = PBXGroup; + children = ( + D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */, + D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */, + ); + path = CompositionalLayout; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -797,6 +859,7 @@ files = ( 5AE176022667DA3F00D4DCE1 /* ListCollectionViewAdapter+UIScrollViewDelegate.swift in Sources */, 5AE175ED2667DA3F00D4DCE1 /* SectionDelegate.swift in Sources */, + D91425852BBBFB840005E8CD /* ListCollectionViewAdapter.swift in Sources */, 5AE175EE2667DA3F00D4DCE1 /* BaseSectionController.swift in Sources */, 5AE1760B2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDropDelegate.swift in Sources */, 5AE176072667DA3F00D4DCE1 /* Section.swift in Sources */, @@ -808,10 +871,12 @@ 5AE175F42667DA3F00D4DCE1 /* SectionDragDelegate.swift in Sources */, 5AE176062667DA3F00D4DCE1 /* ListCollectionViewAdapterDataSource.swift in Sources */, 5AE175F62667DA3F00D4DCE1 /* CollectionViewContext+Size.swift in Sources */, + D93269A22BBBFC2400B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, + D9CCE9B52BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift in Sources */, 5AE175F52667DA3F00D4DCE1 /* CollectionViewAdapter.swift in Sources */, 5AE175F32667DA3F00D4DCE1 /* SectionController.swift in Sources */, 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift in Sources */, - 5AE176042667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */, + D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */, 5AB6644626A854A9004DC230 /* ErrorHandling.swift in Sources */, 5AE176052667DA3F00D4DCE1 /* FoundationDiffingListCollectionViewAdapter.swift in Sources */, 5AE175E92667DA3F00D4DCE1 /* CollectionViewSectionBatchOperation.swift in Sources */, @@ -820,14 +885,13 @@ 5AE175EC2667DA3F00D4DCE1 /* SectionIndexPath.swift in Sources */, 5AE1760F2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */, 5AE1760A2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, - 5AE175FE2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */, 5AE175F12667DA3F00D4DCE1 /* SingleModelSectionController.swift in Sources */, 5AE175FB2667DA3F00D4DCE1 /* CollectionViewUpdate.swift in Sources */, 5AE175E42667DA3F00D4DCE1 /* Collection+Extensions.swift in Sources */, - 5AE176032667DA3F00D4DCE1 /* ListCollectionViewAdapter.swift in Sources */, 5AE175E12667DA3F00D4DCE1 /* IndexPath+IsValid.swift in Sources */, 5AE175F82667DA3F00D4DCE1 /* MainCollectionViewContext.swift in Sources */, - 5AE175FF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, + D91425862BBBFB930005E8CD /* BaseFlowLayoutSectionController.swift in Sources */, + D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */, 5AE176102667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+Convenience.swift in Sources */, 5AE175DE2667DA3F00D4DCE1 /* Sequence+Unique.swift in Sources */, 5AB6644426A85463004DC230 /* Error.swift in Sources */, @@ -840,6 +904,7 @@ 5AE175F02667DA3F00D4DCE1 /* SingleItemSectionController.swift in Sources */, 5AE175FD2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDropDelegate.swift in Sources */, 5AE176092667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDelegate.swift in Sources */, + D93269A32BBBFC2700B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */, 5AE1760C2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UIScrollViewDelegate.swift in Sources */, 5A98000B2678D6BD00378EB5 /* Array+SectionIndexPath.swift in Sources */, 5AE175FA2667DA3F00D4DCE1 /* CollectionViewContext+CollectionViewUpdate.swift in Sources */, @@ -848,6 +913,7 @@ 5AE176012667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegate.swift in Sources */, 5AE1760E2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapterDataSource.swift in Sources */, 5AE176112667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift in Sources */, + D93269A42BBBFC2B00B33C32 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */, 5AE175FC2667DA3F00D4DCE1 /* ListCollectionViewAdapter+Convenience.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -861,12 +927,13 @@ 5A0B775626B0050800B054D4 /* MockSectionDropDelegate.swift in Sources */, 5A0B774B26AEEB3100B054D4 /* SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift in Sources */, 5AB6643026A59626004DC230 /* BaseCollectionViewAdapterUICollectionViewDataSourceTests.swift in Sources */, - 5A31B8D526BAE95700036A3F /* BaseSectionFlowDelegateTests.swift in Sources */, + D91425872BBBFBA40005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift in Sources */, 5A31B8D326BAE94E00036A3F /* ProtocolDefaultValuesSectionDropDelegateTests.swift in Sources */, 5A0B776626B146EC00B054D4 /* ListCollectionViewAdapterUICollectionViewDragDelegateTests.swift in Sources */, 5AA9D96A26AACACF00679D88 /* MockSectionDelegate.swift in Sources */, 5A0B778626B2AB7800B054D4 /* BaseSectionControllerTests.swift in Sources */, 5A0B777026B19EB300B054D4 /* MockListCollectionViewAdapterDataSource.swift in Sources */, + D914257F2BBBF8310005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift in Sources */, 5A31B8E426BC36C400036A3F /* CollectionViewContextExtensionsTests.swift in Sources */, 5AA9D96E26AAD06100679D88 /* SingleSectionCollectionViewAdapterUICollectionViewDelegateTests.swift in Sources */, 5AE1761E2667DA7000D4DCE1 /* SequenceUniqueTests.swift in Sources */, @@ -900,6 +967,7 @@ 5A0B778926B3EA4D00B054D4 /* ErrorTests.swift in Sources */, 5A31B8E226BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift in Sources */, 5AA9D95426AAA5EA00679D88 /* MockCollectionReusableView.swift in Sources */, + D91425822BBBF8780005E8CD /* MockFlowLayoutSectionController.swift in Sources */, 5A0B777C26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift in Sources */, 5A0B774526AED0F600B054D4 /* BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift in Sources */, 5A31B8C326BAE90300036A3F /* BaseSectionDelegateTests.swift in Sources */, @@ -909,7 +977,6 @@ 5AA9D96326AAC65200679D88 /* ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift in Sources */, 5AE1761B2667DA7000D4DCE1 /* SectionIndexPathTests.swift in Sources */, 5AA9D96C26AAD05400679D88 /* ListCollectionViewAdapterUICollectionViewDelegateTests.swift in Sources */, - 5A31B8D726BAE96000036A3F /* BaseSectionControllerSectionFlowDelegateTests.swift in Sources */, 5A31B8C726BAE91300036A3F /* ProtocolDefaultValuesSectionDelegateTests.swift in Sources */, 5A0B776A26B1826100B054D4 /* ListCollectionViewAdapterTests.swift in Sources */, 5A31B8B926BAE8C600036A3F /* BaseSectionControllerSectionDataSourceTests.swift in Sources */, @@ -923,6 +990,7 @@ 5A31B8CD26BAE92D00036A3F /* ProtocolDefaultValuesSectionDragDelegateTests.swift in Sources */, 5A0B774726AEE24700B054D4 /* MockSectionFlowDelegate.swift in Sources */, 5AA9D95826AAA65900679D88 /* ListCollectionViewAdapterUICollectionViewDataSourceTests.swift in Sources */, + D91425692BBBF79E0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift in Sources */, 5AB6644926A86F4D004DC230 /* MockSectionDataSource.swift in Sources */, 5A31B8D126BAE94500036A3F /* BaseSectionControllerSectionDropDelegateTests.swift in Sources */, 5A31B8C526BAE90B00036A3F /* BaseSectionControllerSectionDelegateTests.swift in Sources */, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift index 887b5b98..121bd8c5 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift @@ -2,7 +2,6 @@ import UIKit import XCTest -@MainActor internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() @@ -22,6 +21,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } + @MainActor internal func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], @@ -33,7 +33,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } // MARK: - sizeForItem - + @MainActor internal func testSizeForItemWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() @@ -44,7 +44,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._sizeForItem = { indexPath, layout, _ in @@ -66,6 +66,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: waitForExpectations(timeout: 1) } + @MainActor internal func testSizeForItemWithoutDelegateButWithFlowLayout() throws { let itemSize = CGSize(width: 1, height: 2) let layout = UICollectionViewFlowLayout() @@ -76,7 +77,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -88,6 +89,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: ) } + @MainActor internal func testSizeForItemWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) @@ -96,7 +98,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -110,6 +112,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - inset + @MainActor internal func testInsetWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() @@ -119,7 +122,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._inset = { layout, _ in @@ -140,6 +143,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: waitForExpectations(timeout: 1) } + @MainActor internal func testInsetWithoutDelegateButWithFlowLayout() throws { let sectionInset = UIEdgeInsets(top: 1, left: 2, bottom: 4, right: 8) let layout = UICollectionViewFlowLayout() @@ -149,7 +153,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -161,6 +165,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: ) } + @MainActor internal func testInsetWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) @@ -168,7 +173,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -182,6 +187,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - minimumLineSpacing + @MainActor internal func testMinimumLineSpacingWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() @@ -191,7 +197,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._minimumLineSpacing = { layout, _ in @@ -212,6 +218,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: waitForExpectations(timeout: 1) } + @MainActor internal func testMinimumLineSpacingWithoutDelegateButWithFlowLayout() throws { let lineSpacing: CGFloat = 1 let layout = UICollectionViewFlowLayout() @@ -221,7 +228,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -233,6 +240,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: ) } + @MainActor internal func testMinimumLineSpacingWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) @@ -240,7 +248,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -254,6 +262,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - minimumInteritemSpacing + @MainActor internal func testMinimumInteritemSpacingWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() @@ -263,7 +272,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._minimumInteritemSpacing = { layout, _ in @@ -284,6 +293,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: waitForExpectations(timeout: 1) } + @MainActor internal func testMinimumInteritemSpacingWithoutDelegateButWithFlowLayout() throws { let interitemSpacing: CGFloat = 1 let layout = UICollectionViewFlowLayout() @@ -293,7 +303,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -305,6 +315,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: ) } + @MainActor internal func testMinimumInteritemSpacingWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) @@ -312,7 +323,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -326,6 +337,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - referenceSizeForHeader + @MainActor internal func testReferenceSizeForHeaderWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() @@ -335,7 +347,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._referenceSizeForHeader = { layout, _ in @@ -356,6 +368,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: waitForExpectations(timeout: 1) } + @MainActor internal func testReferenceSizeForHeaderWithoutDelegateButWithFlowLayout() throws { let headerSize = CGSize(width: 1, height: 2) let layout = UICollectionViewFlowLayout() @@ -365,7 +378,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -377,6 +390,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: ) } + @MainActor internal func testReferenceSizeForHeaderWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) @@ -384,7 +398,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -398,6 +412,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - referenceSizeForFooter + @MainActor internal func testReferenceSizeForFooterWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() @@ -407,7 +422,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._referenceSizeForFooter = { layout, _ in @@ -428,6 +443,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: waitForExpectations(timeout: 1) } + @MainActor internal func testReferenceSizeForFooterWithoutDelegateButWithFlowLayout() throws { let footerSize = CGSize(width: 1, height: 2) let layout = UICollectionViewFlowLayout() @@ -437,7 +453,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) @@ -449,6 +465,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: ) } + @MainActor internal func testReferenceSizeForFooterWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) @@ -456,7 +473,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockSectionController() + let sectionController = MockFlowLayoutSectionController() sectionController.flowDelegate = nil return sectionController }) diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/ListCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/ListCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift index 7227d369..afc5972c 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/ListCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/ListCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift @@ -2,9 +2,9 @@ import UIKit import XCTest -@MainActor -internal final class ListCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests { - override internal func createCollectionViewAdapter( +final class ListCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift new file mode 100644 index 00000000..e87dfe9d --- /dev/null +++ b/SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift @@ -0,0 +1,10 @@ +import SectionKit +import XCTest + +internal final class BaseFlowLayoutSectionControllerTests: XCTestCase { + @MainActor + internal func testFlowDelegateIsSelf() { + let sectionController = BaseFlowLayoutSectionController() + XCTAssert(sectionController.flowDelegate === sectionController) + } +} diff --git a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift index 26a3edb7..7598ce13 100644 --- a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift @@ -24,11 +24,6 @@ internal final class BaseSectionControllerTests: XCTestCase { XCTAssert(sectionController.delegate === sectionController) } - internal func testFlowDelegateIsSelf() { - let sectionController = BaseSectionController() - XCTAssert(sectionController.flowDelegate === sectionController) - } - @available(iOS 11.0, *) internal func testDragDelegateIsSelf() { let sectionController = BaseSectionController() diff --git a/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift b/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift index a63371e8..d01408be 100644 --- a/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift @@ -1,42 +1,45 @@ import SectionKit import XCTest -@MainActor -internal final class ProtocolDefaultValuesSectionControllerTests: XCTestCase { - private func createSectionController() -> SectionController { +final class ProtocolDefaultValuesSectionControllerTests: XCTestCase { + private var sut: SectionController! + + @MainActor + override func setUp() { + super.setUp() class DefaultSectionController: SectionController { var context: CollectionViewContext? var dataSource: SectionDataSource = MockSectionDataSource() func didUpdate(model: Any) { } } - return DefaultSectionController() + sut = DefaultSectionController() } - @available(iOS 10.0, *) - internal func testDataSourcePrefetchingDelegateIsNil() { - let sectionController = createSectionController() - XCTAssertNil(sectionController.dataSourcePrefetchingDelegate) + override func tearDown() { + sut = nil + super.tearDown() } - internal func testDelegateIsNil() { - let sectionController = createSectionController() - XCTAssertNil(sectionController.delegate) + @MainActor + @available(iOS 10.0, *) + func testDataSourcePrefetchingDelegateIsNil() { + XCTAssertNil(sut.dataSourcePrefetchingDelegate) } - internal func testFlowDelegateIsNil() { - let sectionController = createSectionController() - XCTAssertNil(sectionController.flowDelegate) + @MainActor + func testDelegateIsNil() { + XCTAssertNil(sut.delegate) } + @MainActor @available(iOS 11.0, *) - internal func testDragDelegateIsNil() { - let sectionController = createSectionController() - XCTAssertNil(sectionController.dragDelegate) + func testDragDelegateIsNil() { + XCTAssertNil(sut.dragDelegate) } + @MainActor @available(iOS 11.0, *) - internal func testDropDelegateIsNil() { - let sectionController = createSectionController() - XCTAssertNil(sectionController.dropDelegate) + func testDropDelegateIsNil() { + XCTAssertNil(sut.dropDelegate) } } diff --git a/SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift new file mode 100644 index 00000000..528568ba --- /dev/null +++ b/SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift @@ -0,0 +1,24 @@ +@testable import SectionKit +import XCTest + +final class BaseCompositionalLayoutSectionControllerTests: XCTestCase { + final class TestLayoutEnvironment: NSObject, NSCollectionLayoutEnvironment { + final class TestLayoutContainer: NSObject, NSCollectionLayoutContainer { + let contentSize: CGSize = .zero + let effectiveContentSize: CGSize = .zero + let contentInsets: NSDirectionalEdgeInsets = .zero + let effectiveContentInsets: NSDirectionalEdgeInsets = .zero + } + let container: NSCollectionLayoutContainer = TestLayoutContainer() + let traitCollection: UITraitCollection = .current + } + + @MainActor + func test_layout_isEmpty() { + let sut = BaseCompositionalLayoutSectionController() + let layoutSection = sut.layoutSection( + layoutEnvironment: TestLayoutEnvironment() + ) + XCTAssertEqual(layoutSection, .empty) + } +} diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift new file mode 100644 index 00000000..4710fa1d --- /dev/null +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift @@ -0,0 +1,9 @@ +import SectionKit +import XCTest + +internal final class BaseFlowLayoutSectionControllerSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { + @MainActor + override func createSectionFlowDelegate() throws -> SectionFlowDelegate { + BaseFlowLayoutSectionController() + } +} diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift similarity index 96% rename from SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionFlowDelegateTests.swift rename to SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift index d6700d55..526003c5 100644 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionFlowDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift @@ -1,8 +1,7 @@ import SectionKit import XCTest -@MainActor -internal class BaseSectionFlowDelegateTests: XCTestCase { +internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false @@ -10,14 +9,16 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { } internal func skipIfNeeded() throws { - guard Self.self === BaseSectionFlowDelegateTests.self else { return } + guard Self.self === BaseFlowLayoutSectionFlowDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } + @MainActor internal func createSectionFlowDelegate() throws -> SectionFlowDelegate { throw XCTSkip("Tests from base class are skipped") } + @MainActor internal func testSizeForItemWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -39,6 +40,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testSizeForItemWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -58,6 +60,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testInsetWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -77,6 +80,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testInsetWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -94,6 +98,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testMinimumLineSpacingWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -112,6 +117,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testMinimumLineSpacingWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -129,6 +135,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testMinimumInteritemSpacingWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -147,6 +154,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testMinimumInteritemSpacingWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -164,6 +172,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testReferenceSizeForHeaderWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -183,6 +192,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testReferenceSizeForHeaderWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -200,6 +210,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testReferenceSizeForFooterWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( @@ -219,6 +230,7 @@ internal class BaseSectionFlowDelegateTests: XCTestCase { ) } + @MainActor internal func testReferenceSizeForFooterWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionControllerSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionControllerSectionFlowDelegateTests.swift deleted file mode 100644 index 6624c139..00000000 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseSectionControllerSectionFlowDelegateTests.swift +++ /dev/null @@ -1,9 +0,0 @@ -import SectionKit -import XCTest - -@MainActor -internal final class BaseSectionControllerSectionFlowDelegateTests: BaseSectionFlowDelegateTests { - override func createSectionFlowDelegate() throws -> SectionFlowDelegate { - BaseSectionController() - } -} diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift index 11d7246e..8dd8e583 100644 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift @@ -2,7 +2,7 @@ import SectionKit import XCTest @MainActor -internal final class ProtocolDefaultValuesSectionFlowDelegateTests: BaseSectionFlowDelegateTests { +internal final class ProtocolDefaultValuesSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { override func createSectionFlowDelegate() throws -> SectionFlowDelegate { class DefaultSectionFlowDelegate: SectionFlowDelegate { } return DefaultSectionFlowDelegate() diff --git a/SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift b/SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift new file mode 100644 index 00000000..7cf6be8f --- /dev/null +++ b/SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift @@ -0,0 +1,10 @@ +import SectionKit +import XCTest + +final class MockFlowLayoutSectionController: MockSectionController, + FlowLayoutSectionController { + lazy var flowDelegate: SectionFlowDelegate? = { + XCTFail("flow delegate is not set") + return nil + }() +} diff --git a/SectionKit/Tests/TestUtilities/MockSectionController.swift b/SectionKit/Tests/TestUtilities/MockSectionController.swift index f787dbf6..b6a8d80f 100644 --- a/SectionKit/Tests/TestUtilities/MockSectionController.swift +++ b/SectionKit/Tests/TestUtilities/MockSectionController.swift @@ -20,11 +20,6 @@ internal class MockSectionController: SectionController { return nil }() - internal lazy var flowDelegate: SectionFlowDelegate? = { - XCTFail("flow delegate is not set") - return nil - }() - @available(iOS 11.0, *) internal lazy var dragDelegate: SectionDragDelegate? = { XCTFail("dragDelegate is not set") From ba14a562115a089326e605618951dd1805e99107 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 12:17:10 +0200 Subject: [PATCH 05/24] add references --- SectionKit.xcodeproj/project.pbxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index fdbbd9d8..ff259593 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -140,6 +140,7 @@ D93269A22BBBFC2400B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CA2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift */; }; D93269A32BBBFC2700B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C92667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift */; }; D93269A42BBBFC2B00B33C32 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift */; }; + D941851A2BBC123C001B5086 /* ListCompositionalLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */; }; D9CCE9B52BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */; }; D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */; }; /* End PBXBuildFile section */ @@ -887,6 +888,7 @@ 5AE1760A2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, 5AE175F12667DA3F00D4DCE1 /* SingleModelSectionController.swift in Sources */, 5AE175FB2667DA3F00D4DCE1 /* CollectionViewUpdate.swift in Sources */, + D941851A2BBC123C001B5086 /* ListCompositionalLayoutSectionController.swift in Sources */, 5AE175E42667DA3F00D4DCE1 /* Collection+Extensions.swift in Sources */, 5AE175E12667DA3F00D4DCE1 /* IndexPath+IsValid.swift in Sources */, 5AE175F82667DA3F00D4DCE1 /* MainCollectionViewContext.swift in Sources */, From 8cfb78683429444495a087d80ace4394136ae557 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 14:03:01 +0200 Subject: [PATCH 06/24] Fix warnings --- ...CollectionViewContextExtensionsTests.swift | 85 ++++----- .../CollectionViewContextSizeTests.swift | 15 +- .../MainCollectionViewContextTests.swift | 63 ++++--- .../ListCollectionViewAdapterTests.swift | 126 +++++++++----- ...gleSectionCollectionViewAdapterTests.swift | 135 +++++++++----- ...apterUICollectionViewDataSourceTests.swift | 64 ++++--- ...apterUICollectionViewDataSourceTests.swift | 6 +- ...apterUICollectionViewDataSourceTests.swift | 4 +- ...ectionViewDataSourcePrefetchingTests.swift | 22 ++- ...ectionViewDataSourcePrefetchingTests.swift | 6 +- ...ectionViewDataSourcePrefetchingTests.swift | 6 +- ...AdapterUICollectionViewDelegateTests.swift | 164 ++++++++++++------ ...AdapterUICollectionViewDelegateTests.swift | 4 +- ...AdapterUICollectionViewDelegateTests.swift | 4 +- ...ollectionViewDelegateFlowLayoutTests.swift | 6 +- ...terUICollectionViewDragDelegateTests.swift | 40 +++-- ...terUICollectionViewDragDelegateTests.swift | 6 +- ...terUICollectionViewDropDelegateTests.swift | 73 +++++--- ...terUICollectionViewDropDelegateTests.swift | 4 +- ...terUICollectionViewDropDelegateTests.swift | 6 +- ...ViewAdapterUIScrollViewDelegateTests.swift | 52 ++++-- ...ViewAdapterUIScrollViewDelegateTests.swift | 6 +- ...ViewAdapterUIScrollViewDelegateTests.swift | 6 +- .../BaseSectionControllerTests.swift | 24 ++- .../ListSectionControllerTests.swift | 24 ++- ...tionControllerSectionDataSourceTests.swift | 4 +- .../BaseSectionDataSourceTests.swift | 26 +-- ...lDefaultValuesSectionDataSourceTests.swift | 4 +- ...onDataSourcePrefetchingDelegateTests.swift | 4 +- ...onDataSourcePrefetchingDelegateTests.swift | 14 +- ...onDataSourcePrefetchingDelegateTests.swift | 4 +- ...ectionControllerSectionDelegateTests.swift | 4 +- .../BaseSectionDelegateTests.swift | 71 +++++--- ...colDefaultValuesSectionDelegateTests.swift | 4 +- ...onControllerSectionDragDelegateTests.swift | 4 +- .../BaseSectionDragDelegateTests.swift | 23 ++- ...efaultValuesSectionDragDelegateTests.swift | 1 + ...onControllerSectionDropDelegateTests.swift | 4 +- .../BaseSectionDropDelegateTests.swift | 29 ++-- ...efaultValuesSectionDropDelegateTests.swift | 2 +- ...onControllerSectionFlowDelegateTests.swift | 2 +- ...seFlowLayoutSectionFlowDelegateTests.swift | 30 ++-- ...efaultValuesSectionFlowDelegateTests.swift | 4 +- .../SingleItemSectionControllerTests.swift | 42 +++-- .../SingleModelSectionControllerTests.swift | 15 +- .../Utility/UICollectionViewApplyTests.swift | 30 ++-- 46 files changed, 781 insertions(+), 491 deletions(-) diff --git a/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextExtensionsTests.swift b/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextExtensionsTests.swift index 1a2a862c..3fcebf11 100644 --- a/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextExtensionsTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextExtensionsTests.swift @@ -1,16 +1,31 @@ @testable import SectionKit import XCTest -@MainActor -internal final class CollectionViewContextExtensionsTests: XCTestCase { - // MARK: - dequeueReusableCell +final class CollectionViewContextExtensionsTests: XCTestCase { + private var context: MockCollectionViewContext! - internal func testDequeueReusableCellForIndexPathWithImplicitType() { - let testExpectation = expectation(description: "Should invoke dequeueReusableCell") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), + @MainActor + override func setUp() { + super.setUp() + context = MockCollectionViewContext( + collectionView: UICollectionView( + frame: .zero, + collectionViewLayout: UICollectionViewFlowLayout() + ), errorHandler: MockErrorHandler() ) + } + + override func tearDown() { + context = nil + super.tearDown() + } + + // MARK: - dequeueReusableCell + + @MainActor + func testDequeueReusableCellForIndexPathWithImplicitType() { + let testExpectation = expectation(description: "Should invoke dequeueReusableCell") context._dequeueReusableCell = { cellType, indexPath in XCTAssert(cellType === MockCollectionViewCell.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -21,12 +36,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableCellForSectionIndexPathWithExplicitType() { + @MainActor + func testDequeueReusableCellForSectionIndexPathWithExplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableCell") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableCell = { cellType, indexPath in XCTAssert(cellType === MockCollectionViewCell.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -37,12 +49,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableCellForSectionIndexPathWithImplicitType() { + @MainActor + func testDequeueReusableCellForSectionIndexPathWithImplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableCell") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableCell = { cellType, indexPath in XCTAssert(cellType === MockCollectionViewCell.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -55,12 +64,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { // MARK: - dequeueReusableHeaderView - internal func testDequeueReusableHeaderViewForIndexPathWithImplicitType() { + @MainActor + func testDequeueReusableHeaderViewForIndexPathWithImplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableHeaderView") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableHeaderView = { cellType, indexPath in XCTAssert(cellType === MockCollectionReusableView.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -71,12 +77,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableHeaderViewForSectionIndexPathWithExplicitType() { + @MainActor + func testDequeueReusableHeaderViewForSectionIndexPathWithExplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableHeaderView") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableHeaderView = { cellType, indexPath in XCTAssert(cellType === MockCollectionReusableView.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -87,12 +90,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableHeaderViewForSectionIndexPathWithImplicitType() { + @MainActor + func testDequeueReusableHeaderViewForSectionIndexPathWithImplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableHeaderView") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableHeaderView = { cellType, indexPath in XCTAssert(cellType === MockCollectionReusableView.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -105,12 +105,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { // MARK: - dequeueReusableFooterView - internal func testDequeueReusableFooterViewForIndexPathWithImplicitType() { + @MainActor + func testDequeueReusableFooterViewForIndexPathWithImplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableFooterView") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableFooterView = { cellType, indexPath in XCTAssert(cellType === MockCollectionReusableView.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -121,12 +118,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableFooterViewForSectionIndexPathWithExplicitType() { + @MainActor + func testDequeueReusableFooterViewForSectionIndexPathWithExplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableFooterView") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableFooterView = { cellType, indexPath in XCTAssert(cellType === MockCollectionReusableView.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) @@ -137,12 +131,9 @@ internal final class CollectionViewContextExtensionsTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableFooterViewForSectionIndexPathWithImplicitType() { + @MainActor + func testDequeueReusableFooterViewForSectionIndexPathWithImplicitType() { let testExpectation = expectation(description: "Should invoke dequeueReusableFooterView") - let context = MockCollectionViewContext( - collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), - errorHandler: MockErrorHandler() - ) context._dequeueReusableFooterView = { cellType, indexPath in XCTAssert(cellType === MockCollectionReusableView.self) XCTAssertEqual(indexPath, IndexPath(item: 0, section: 0)) diff --git a/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextSizeTests.swift b/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextSizeTests.swift index 7f8e60ce..ff4d96e7 100644 --- a/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextSizeTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/CollectionViewContextSizeTests.swift @@ -1,9 +1,9 @@ @testable import SectionKit import XCTest -@MainActor -internal final class CollectionViewContextSizeTests: XCTestCase { - internal func testContainerSize() { +final class CollectionViewContextSizeTests: XCTestCase { + @MainActor + func testContainerSize() { let rect = CGRect(x: 1, y: 2, width: 4, height: 8) let collectionView = UICollectionView(frame: rect, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( @@ -14,7 +14,8 @@ internal final class CollectionViewContextSizeTests: XCTestCase { XCTAssertEqual(context.containerSize, rect.size) } - internal func testCustomContainerInset() { + @MainActor + func testCustomContainerInset() { let insets = UIEdgeInsets(top: 1, left: 2, bottom: 4, right: 8) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) collectionView.contentInset = insets @@ -26,7 +27,8 @@ internal final class CollectionViewContextSizeTests: XCTestCase { XCTAssertEqual(context.customContainerInset, insets) } - internal func testAdjustedContainerInset() { + @MainActor + func testAdjustedContainerInset() { let insets = UIEdgeInsets(top: 1, left: 2, bottom: 4, right: 8) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) collectionView.contentInset = insets @@ -38,7 +40,8 @@ internal final class CollectionViewContextSizeTests: XCTestCase { XCTAssertEqual(context.adjustedContainerInset, insets) } - internal func testInsetContainerSize() { + @MainActor + func testInsetContainerSize() { let rect = CGRect(x: 16, y: 32, width: 64, height: 128) let insets = UIEdgeInsets(top: 1, left: 2, bottom: 4, right: 8) let collectionView = UICollectionView(frame: rect, collectionViewLayout: UICollectionViewFlowLayout()) diff --git a/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/MainCollectionViewContextTests.swift b/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/MainCollectionViewContextTests.swift index e70c8554..94849d55 100644 --- a/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/MainCollectionViewContextTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/CollectionViewContext/MainCollectionViewContextTests.swift @@ -1,9 +1,9 @@ @testable import SectionKit import XCTest -@MainActor -internal final class MainCollectionViewContextTests: XCTestCase { - internal func testAdapterIsWeakReferenced() { +final class MainCollectionViewContextTests: XCTestCase { + @MainActor + func testAdapterIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( viewController: nil, @@ -16,7 +16,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { XCTAssertNil(context.adapter) } - internal func testViewControllerIsWeakReferenced() { + @MainActor + func testViewControllerIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( viewController: UIViewController(), @@ -26,7 +27,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { XCTAssertNil(context.viewController) } - internal func testApplySectionUpdate() { + @MainActor + func testApplySectionUpdate() { let collectionViewExpectation = expectation(description: "reloadData should be invoked") let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) collectionView._reloadData = collectionViewExpectation.fulfill @@ -52,7 +54,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testApplySectionUpdateWhenAdapterIsNotSetThenReloadDataIsCalled() { + @MainActor + func testApplySectionUpdateWhenAdapterIsNotSetThenReloadDataIsCalled() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let collectionViewExpectation = expectation(description: "reloadData should be invoked") let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -78,7 +81,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testApplySectionUpdateWhenSectionControllerIsNotPartOfTheAdapterThenReloadDataIsCalled() { + @MainActor + func testApplySectionUpdateWhenSectionControllerIsNotPartOfTheAdapterThenReloadDataIsCalled() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let collectionViewExpectation = expectation(description: "reloadData should be invoked") let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -106,7 +110,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableCellWhenCellIsNotRegisteredYet() { + @MainActor + func testDequeueReusableCellWhenCellIsNotRegisteredYet() { let registerExpectation = expectation(description: "The cell should be registered") let dequeueExpectation = expectation(description: "The cell should be dequeued") let mockIndexPath = IndexPath(item: 1, section: 2) @@ -137,7 +142,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableCellWhenCellIsAlreadyRegistered() { + @MainActor + func testDequeueReusableCellWhenCellIsAlreadyRegistered() { let registerExpectation = expectation(description: "The cell should not be registered") registerExpectation.fulfill() let dequeueExpectation = expectation(description: "The cell should be dequeued") @@ -168,7 +174,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableCellWhenInvalidCellIsRegistered() { + @MainActor + func testDequeueReusableCellWhenInvalidCellIsRegistered() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let dequeueExpectation = expectation(description: "The cell should be dequeued") let mockIndexPath = IndexPath(item: 1, section: 2) @@ -202,7 +209,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableHeaderViewWhenHeaderViewIsNotRegisteredYet() { + @MainActor + func testDequeueReusableHeaderViewWhenHeaderViewIsNotRegisteredYet() { let registerExpectation = expectation(description: "The header view should be registered") let dequeueExpectation = expectation(description: "The header view should be dequeued") let mockIndexPath = IndexPath(item: 1, section: 2) @@ -235,7 +243,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableHeaderViewWhenHeaderViewIsAlreadyRegistered() { + @MainActor + func testDequeueReusableHeaderViewWhenHeaderViewIsAlreadyRegistered() { let registerExpectation = expectation(description: "The header view should not be registered") registerExpectation.fulfill() let dequeueExpectation = expectation(description: "The header view should be dequeued") @@ -267,7 +276,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableHeaderViewWhenInvalidHeaderViewIsRegistered() { + @MainActor + func testDequeueReusableHeaderViewWhenInvalidHeaderViewIsRegistered() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let dequeueExpectation = expectation(description: "The header view should be dequeued") let mockIndexPath = IndexPath(item: 1, section: 2) @@ -302,7 +312,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableFooterViewWhenFooterViewIsNotRegisteredYet() { + @MainActor + func testDequeueReusableFooterViewWhenFooterViewIsNotRegisteredYet() { let registerExpectation = expectation(description: "The footer view should be registered") let dequeueExpectation = expectation(description: "The footer view should be dequeued") let mockIndexPath = IndexPath(item: 1, section: 2) @@ -335,7 +346,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableFooterViewWhenFooterViewIsAlreadyRegistered() { + @MainActor + func testDequeueReusableFooterViewWhenFooterViewIsAlreadyRegistered() { let registerExpectation = expectation(description: "The footer view should not be registered") registerExpectation.fulfill() let dequeueExpectation = expectation(description: "The footer view should be dequeued") @@ -367,7 +379,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testDequeueReusableFooterViewWhenInvalidFooterViewIsRegistered() { + @MainActor + func testDequeueReusableFooterViewWhenInvalidFooterViewIsRegistered() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let dequeueExpectation = expectation(description: "The footer view should be dequeued") let mockIndexPath = IndexPath(item: 1, section: 2) @@ -402,7 +415,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSectionControllerWithAdjustedIndexPath() { + @MainActor + func testSectionControllerWithAdjustedIndexPath() { let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( viewController: nil, @@ -423,7 +437,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { XCTAssertEqual(actual?.1.indexInCollectionView, indexPath) } - internal func testSectionControllerWithAdjustedIndexPathWhenSectionDoesNotExist() { + @MainActor + func testSectionControllerWithAdjustedIndexPathWhenSectionDoesNotExist() { let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( viewController: nil, @@ -435,7 +450,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { XCTAssertNil(context.sectionControllerWithAdjustedIndexPath(for: IndexPath(item: 0, section: 0))) } - internal func testSectionControllerWithAdjustedIndexPathWhenAdapterIsNotSet() { + @MainActor + func testSectionControllerWithAdjustedIndexPathWhenAdapterIsNotSet() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( @@ -454,7 +470,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testIndexOfControllerWhenAdapterIsNotSet() { + @MainActor + func testIndexOfControllerWhenAdapterIsNotSet() { let errorExpectation = expectation(description: "The errorHandler should be invoked") let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let context = MainCollectionViewContext( @@ -473,7 +490,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testIndexOfControllerThatIsNotPartOfTheContext() { + @MainActor + func testIndexOfControllerThatIsNotPartOfTheContext() { let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = MockCollectionViewAdapter() adapter._sections = { [] } @@ -486,7 +504,8 @@ internal final class MainCollectionViewContextTests: XCTestCase { XCTAssertNil(context.index(of: MockSectionController())) } - internal func testIndexOfControllerThatIsPartOfTheContext() { + @MainActor + func testIndexOfControllerThatIsPartOfTheContext() { let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let controller = MockSectionController() let adapter = MockCollectionViewAdapter() diff --git a/SectionKit/Tests/CollectionViewAdapter/ListCollectionViewAdapterTests.swift b/SectionKit/Tests/CollectionViewAdapter/ListCollectionViewAdapterTests.swift index e2edd149..9362dac9 100644 --- a/SectionKit/Tests/CollectionViewAdapter/ListCollectionViewAdapterTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/ListCollectionViewAdapterTests.swift @@ -1,11 +1,11 @@ @testable import SectionKit import XCTest -@MainActor -internal final class ListCollectionViewAdapterTests: XCTestCase { +final class ListCollectionViewAdapterTests: XCTestCase { // MARK: - Init with datasource - internal func testInitWithDataSourceSetsDataSource() { + @MainActor + func testInitWithDataSourceSetsDataSource() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -15,7 +15,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.dataSource === dataSource) } - internal func testInitWithDataSourceSetsViewController() { + @MainActor + func testInitWithDataSourceSetsViewController() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let viewController = UIViewController() @@ -27,7 +28,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.viewController === viewController) } - internal func testInitWithDataSourceSetsScrollViewDelegate() { + @MainActor + func testInitWithDataSourceSetsScrollViewDelegate() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let scrollViewDelegate = MockScrollViewDelegate() @@ -39,7 +41,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.scrollViewDelegate === scrollViewDelegate) } - internal func testInitWithDataSourceSetsErrorHandler() { + @MainActor + func testInitWithDataSourceSetsErrorHandler() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let errorHandler = MockErrorHandler() @@ -51,7 +54,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.errorHandler is MockErrorHandler) } - internal func testInitWithDataSourceRetrievesInitialSections() { + @MainActor + func testInitWithDataSourceRetrievesInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [section] } @@ -63,7 +67,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.sections.first === section) } - internal func testInitWithDataSourceSetsContextOnInitialSections() { + @MainActor + func testInitWithDataSourceSetsContextOnInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [section] } @@ -74,7 +79,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(section.controller.context === adapter.context) } - internal func testInitWithDataSourceSetsCollectionViewDataSourceToSelf() { + @MainActor + func testInitWithDataSourceSetsCollectionViewDataSourceToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -84,8 +90,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithDataSourceSetsCollectionViewDataSourcePrefetchingToSelf() { + func testInitWithDataSourceSetsCollectionViewDataSourcePrefetchingToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -95,8 +102,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.prefetchDataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithDataSourceEnablesDataSourcePrefetchingOnCollectionView() { + func testInitWithDataSourceEnablesDataSourcePrefetchingOnCollectionView() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let _ = ListCollectionViewAdapter( @@ -106,7 +114,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.isPrefetchingEnabled) } - internal func testInitWithDataSourceSetsCollectionViewDelegateToSelf() { + @MainActor + func testInitWithDataSourceSetsCollectionViewDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -116,8 +125,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.delegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithDataSourceSetsCollectionViewDragDelegateToSelf() { + func testInitWithDataSourceSetsCollectionViewDragDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -127,8 +137,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dragDelegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithDataSourceSetsCollectionViewDropDelegateToSelf() { + func testInitWithDataSourceSetsCollectionViewDropDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -138,7 +149,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dropDelegate === adapter) } - internal func testInitWithDataSourceSetsContextAdapterToSelf() { + @MainActor + func testInitWithDataSourceSetsContextAdapterToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockListCollectionViewAdapterDataSource { _ in [] } let adapter = ListCollectionViewAdapter( @@ -150,7 +162,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { // MARK: - Init with sections - internal func testInitWithSectionsDoesNotSetDataSource() { + @MainActor + func testInitWithSectionsDoesNotSetDataSource() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -159,7 +172,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssertNil(adapter.dataSource) } - internal func testInitWithSectionsSetsViewController() { + @MainActor + func testInitWithSectionsSetsViewController() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let viewController = UIViewController() let adapter = ListCollectionViewAdapter( @@ -170,7 +184,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.viewController === viewController) } - internal func testInitWithSectionsSetsScrollViewDelegate() { + @MainActor + func testInitWithSectionsSetsScrollViewDelegate() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let scrollViewDelegate = MockScrollViewDelegate() let adapter = ListCollectionViewAdapter( @@ -181,7 +196,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.scrollViewDelegate === scrollViewDelegate) } - internal func testInitWithSectionsSetsErrorHandler() { + @MainActor + func testInitWithSectionsSetsErrorHandler() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let errorHandler = MockErrorHandler() let adapter = ListCollectionViewAdapter( @@ -192,7 +208,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.errorHandler is MockErrorHandler) } - internal func testInitWithSectionsSetsInitialSections() { + @MainActor + func testInitWithSectionsSetsInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let adapter = ListCollectionViewAdapter( @@ -203,7 +220,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.sections.first === section) } - internal func testInitWithSectionsSetsContextOnInitialSections() { + @MainActor + func testInitWithSectionsSetsContextOnInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let adapter = ListCollectionViewAdapter( @@ -213,7 +231,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(section.controller.context === adapter.context) } - internal func testInitWithSectionsSetsCollectionViewDataSourceToSelf() { + @MainActor + func testInitWithSectionsSetsCollectionViewDataSourceToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -222,8 +241,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithSectionsSetsCollectionViewDataSourcePrefetchingToSelf() { + func testInitWithSectionsSetsCollectionViewDataSourcePrefetchingToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -232,8 +252,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.prefetchDataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithSectionsEnablesDataSourcePrefetchingOnCollectionView() { + func testInitWithSectionsEnablesDataSourcePrefetchingOnCollectionView() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let _ = ListCollectionViewAdapter( collectionView: collectionView, @@ -242,7 +263,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.isPrefetchingEnabled) } - internal func testInitWithSectionsSetsCollectionViewDelegateToSelf() { + @MainActor + func testInitWithSectionsSetsCollectionViewDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -251,8 +273,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.delegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithSectionsSetsCollectionViewDragDelegateToSelf() { + func testInitWithSectionsSetsCollectionViewDragDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -261,8 +284,9 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dragDelegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithSectionsSetsCollectionViewDropDelegateToSelf() { + func testInitWithSectionsSetsCollectionViewDropDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -271,7 +295,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dropDelegate === adapter) } - internal func testInitWithSectionsSetsContextAdapterToSelf() { + @MainActor + func testInitWithSectionsSetsContextAdapterToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -282,7 +307,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { // MARK: - Weak references - internal func testDataSourceIsWeakReferenced() { + @MainActor + func testDataSourceIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -291,7 +317,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssertNil(adapter.dataSource) } - internal func testViewControllerIsWeakReferenced() { + @MainActor + func testViewControllerIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -300,7 +327,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssertNil(adapter.context.viewController) } - internal func testScrollViewDelegateIsWeakReferenced() { + @MainActor + func testScrollViewDelegateIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter( collectionView: collectionView, @@ -311,7 +339,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { // MARK: - Setting CollectionViewSections - internal func testSetCollectionViewSectionsUpdatesContextOnSectionController() { + @MainActor + func testSetCollectionViewSectionsUpdatesContextOnSectionController() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let initialSection = Section(id: "", model: "", controller: MockSectionController()) let adapter = ListCollectionViewAdapter( @@ -324,7 +353,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(newSection.controller.context === adapter.context) } - internal func testInitialSectionsFiltersDuplicateSectionsAndInvokeErrorHandler() { + @MainActor + func testInitialSectionsFiltersDuplicateSectionsAndInvokeErrorHandler() { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let firstSection = Section(id: "", model: "", controller: MockSectionController()) @@ -347,7 +377,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSectionsPropertyFiltersDuplicateSectionsAndInvokesErrorHandler() { + @MainActor + func testSectionsPropertyFiltersDuplicateSectionsAndInvokesErrorHandler() { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let firstSection = Section(id: "", model: "", controller: MockSectionController()) @@ -371,7 +402,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSectionsPropertyFiltersDuplicateSectionsAndInvokesDidUpdateOnlyOnce() { + @MainActor + func testSectionsPropertyFiltersDuplicateSectionsAndInvokesDidUpdateOnlyOnce() { let didUpdateExpectation = expectation(description: "Should invoke SectionController.didUpdate exactly once") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let sectionId = "test" @@ -408,7 +440,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSettingTheDataSourceRetrievesTheListOfSections() { + @MainActor + func testSettingTheDataSourceRetrievesTheListOfSections() { let testExpectation = expectation(description: "Should invoke dataSource") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) @@ -423,7 +456,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testUpdatingTheSectionsReusesSectionControllersWithTheSameId() { + @MainActor + func testUpdatingTheSectionsReusesSectionControllersWithTheSameId() { let testExpectation = expectation(description: "Should invoke didUpdate on the first SectionController") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let firstSection = Section(id: "section", model: "1", controller: { @@ -448,7 +482,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testUpdatingTheSectionsCalculatesAnUpdate() { + @MainActor + func testUpdatingTheSectionsCalculatesAnUpdate() { let testExpectation = expectation(description: "Should invoke calculateUpdate on the adapter") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let firstSection = Section(id: "section", model: "1", controller: { @@ -491,7 +526,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testCallingInvalidateDataSourceRetrievesTheListOfSections() { + @MainActor + func testCallingInvalidateDataSourceRetrievesTheListOfSections() { let testExpectation = expectation(description: "Should invoke dataSource") testExpectation.expectedFulfillmentCount = 2 let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -512,7 +548,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testResettingDataSourceDoesNotRetrieveTheListOfSectionsAgain() { + @MainActor + func testResettingDataSourceDoesNotRetrieveTheListOfSectionsAgain() { let testExpectation = expectation(description: "Should invoke dataSource") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: { @@ -534,7 +571,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { // MARK: - calculateUpdate - internal func testCalculateUpdateReloadsData() throws { + @MainActor + func testCalculateUpdateReloadsData() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter(collectionView: collectionView) let update = try XCTUnwrap(adapter.calculateUpdate(from: [], to: [])) @@ -547,7 +585,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateHasCorrectData() throws { + @MainActor + func testCalculateUpdateHasCorrectData() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter(collectionView: collectionView) let section = Section(id: "1", model: "", controller: MockSectionController()) @@ -563,7 +602,8 @@ internal final class ListCollectionViewAdapterTests: XCTestCase { XCTAssert(batchOperation.data.first === section) } - internal func testCalculateUpdateSetDataSetsCollectionViewSection() throws { + @MainActor + func testCalculateUpdateSetDataSetsCollectionViewSection() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = ListCollectionViewAdapter(collectionView: collectionView) let section = Section(id: "1", model: "", controller: MockSectionController()) diff --git a/SectionKit/Tests/CollectionViewAdapter/SingleSectionCollectionViewAdapterTests.swift b/SectionKit/Tests/CollectionViewAdapter/SingleSectionCollectionViewAdapterTests.swift index f4308b60..6220c34e 100644 --- a/SectionKit/Tests/CollectionViewAdapter/SingleSectionCollectionViewAdapterTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/SingleSectionCollectionViewAdapterTests.swift @@ -1,11 +1,11 @@ @testable import SectionKit import XCTest -@MainActor -internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { +final class SingleSectionCollectionViewAdapterTests: XCTestCase { // MARK: - Init with datasource - internal func testInitWithDataSourceSetsDataSource() { + @MainActor + func testInitWithDataSourceSetsDataSource() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -15,7 +15,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.dataSource === dataSource) } - internal func testInitWithDataSourceSetsViewController() { + @MainActor + func testInitWithDataSourceSetsViewController() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let viewController = UIViewController() @@ -27,7 +28,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.viewController === viewController) } - internal func testInitWithDataSourceSetsScrollViewDelegate() { + @MainActor + func testInitWithDataSourceSetsScrollViewDelegate() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let scrollViewDelegate = MockScrollViewDelegate() @@ -39,7 +41,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.scrollViewDelegate === scrollViewDelegate) } - internal func testInitWithDataSourceSetsErrorHandler() { + @MainActor + func testInitWithDataSourceSetsErrorHandler() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let errorHandler = MockErrorHandler() @@ -51,7 +54,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.errorHandler is MockErrorHandler) } - internal func testInitWithDataSourceRetrievesInitialSections() { + @MainActor + func testInitWithDataSourceRetrievesInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in section } @@ -63,7 +67,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.sections.first === section) } - internal func testInitWithDataSourceSetsContextOnInitialSections() { + @MainActor + func testInitWithDataSourceSetsContextOnInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in section } @@ -74,7 +79,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(section.controller.context === adapter.context) } - internal func testInitWithDataSourceSetsCollectionViewDataSourceToSelf() { + @MainActor + func testInitWithDataSourceSetsCollectionViewDataSourceToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -84,8 +90,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithDataSourceSetsCollectionViewDataSourcePrefetchingToSelf() { + func testInitWithDataSourceSetsCollectionViewDataSourcePrefetchingToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -95,8 +102,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.prefetchDataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithDataSourceEnablesDataSourcePrefetchingOnCollectionView() { + func testInitWithDataSourceEnablesDataSourcePrefetchingOnCollectionView() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let _ = SingleSectionCollectionViewAdapter( @@ -106,7 +114,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.isPrefetchingEnabled) } - internal func testInitWithDataSourceSetsCollectionViewDelegateToSelf() { + @MainActor + func testInitWithDataSourceSetsCollectionViewDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -116,8 +125,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.delegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithDataSourceSetsCollectionViewDragDelegateToSelf() { + func testInitWithDataSourceSetsCollectionViewDragDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -127,8 +137,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dragDelegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithDataSourceSetsCollectionViewDropDelegateToSelf() { + func testInitWithDataSourceSetsCollectionViewDropDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -138,7 +149,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dropDelegate === adapter) } - internal func testInitWithDataSourceSetsContextAdapterToSelf() { + @MainActor + func testInitWithDataSourceSetsContextAdapterToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let dataSource = MockSingleSectionCollectionViewAdapterDataSource { _ in nil } let adapter = SingleSectionCollectionViewAdapter( @@ -150,7 +162,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { // MARK: - Init with sections - internal func testInitWithSectionsDoesNotSetDataSource() { + @MainActor + func testInitWithSectionsDoesNotSetDataSource() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -159,7 +172,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertNil(adapter.dataSource) } - internal func testInitWithSectionsSetsViewController() { + @MainActor + func testInitWithSectionsSetsViewController() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let viewController = UIViewController() let adapter = SingleSectionCollectionViewAdapter( @@ -170,7 +184,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.viewController === viewController) } - internal func testInitWithSectionsSetsScrollViewDelegate() { + @MainActor + func testInitWithSectionsSetsScrollViewDelegate() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let scrollViewDelegate = MockScrollViewDelegate() let adapter = SingleSectionCollectionViewAdapter( @@ -181,7 +196,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.scrollViewDelegate === scrollViewDelegate) } - internal func testInitWithSectionsSetsErrorHandler() { + @MainActor + func testInitWithSectionsSetsErrorHandler() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let errorHandler = MockErrorHandler() let adapter = SingleSectionCollectionViewAdapter( @@ -192,7 +208,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.context.errorHandler is MockErrorHandler) } - internal func testInitWithSectionsSetsInitialSections() { + @MainActor + func testInitWithSectionsSetsInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let adapter = SingleSectionCollectionViewAdapter( @@ -203,7 +220,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.sections.first === section) } - internal func testInitWithSectionsSetsContextOnInitialSections() { + @MainActor + func testInitWithSectionsSetsContextOnInitialSections() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let adapter = SingleSectionCollectionViewAdapter( @@ -213,7 +231,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(section.controller.context === adapter.context) } - internal func testInitWithSectionsSetsCollectionViewDataSourceToSelf() { + @MainActor + func testInitWithSectionsSetsCollectionViewDataSourceToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -222,8 +241,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithSectionsSetsCollectionViewDataSourcePrefetchingToSelf() { + func testInitWithSectionsSetsCollectionViewDataSourcePrefetchingToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -232,8 +252,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.prefetchDataSource === adapter) } + @MainActor @available(iOS 10.0, *) - internal func testInitWithSectionsEnablesDataSourcePrefetchingOnCollectionView() { + func testInitWithSectionsEnablesDataSourcePrefetchingOnCollectionView() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let _ = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -242,7 +263,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.isPrefetchingEnabled) } - internal func testInitWithSectionsSetsCollectionViewDelegateToSelf() { + @MainActor + func testInitWithSectionsSetsCollectionViewDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -251,8 +273,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.delegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithSectionsSetsCollectionViewDragDelegateToSelf() { + func testInitWithSectionsSetsCollectionViewDragDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -261,8 +284,9 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dragDelegate === adapter) } + @MainActor @available(iOS 11.0, *) - internal func testInitWithSectionsSetsCollectionViewDropDelegateToSelf() { + func testInitWithSectionsSetsCollectionViewDropDelegateToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -271,7 +295,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(collectionView.dropDelegate === adapter) } - internal func testInitWithSectionsSetsContextAdapterToSelf() { + @MainActor + func testInitWithSectionsSetsContextAdapterToSelf() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -282,7 +307,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { // MARK: - Weak references - internal func testDataSourceIsWeakReferenced() { + @MainActor + func testDataSourceIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -291,7 +317,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertNil(adapter.dataSource) } - internal func testViewControllerIsWeakReferenced() { + @MainActor + func testViewControllerIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -300,7 +327,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertNil(adapter.context.viewController) } - internal func testScrollViewDelegateIsWeakReferenced() { + @MainActor + func testScrollViewDelegateIsWeakReferenced() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -311,7 +339,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { // MARK: - Setting CollectionViewSections - internal func testSetCollectionViewSectionsUpdatesContextOnSectionController() { + @MainActor + func testSetCollectionViewSectionsUpdatesContextOnSectionController() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let initialSection = Section(id: "", model: "", controller: MockSectionController()) let adapter = SingleSectionCollectionViewAdapter( @@ -324,7 +353,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(newSection.controller.context === adapter.context) } - internal func testSettingTheDataSourceRetrievesTheSection() { + @MainActor + func testSettingTheDataSourceRetrievesTheSection() { let testExpectation = expectation(description: "Should invoke dataSource") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) @@ -339,7 +369,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testUpdatingTheSectionsReusesSectionControllersWithTheSameId() { + @MainActor + func testUpdatingTheSectionsReusesSectionControllersWithTheSameId() { let testExpectation = expectation(description: "Should invoke didUpdate on the first SectionController") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let firstSection = Section(id: "section", model: "1", controller: { @@ -364,7 +395,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testUpdatingTheSectionsCalculatesAnUpdate() { + @MainActor + func testUpdatingTheSectionsCalculatesAnUpdate() { let testExpectation = expectation(description: "Should invoke calculateUpdate on the adapter") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let firstSection = Section(id: "section", model: "1", controller: { @@ -405,7 +437,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testCallingInvalidateDataSourceRetrievesTheSection() { + @MainActor + func testCallingInvalidateDataSourceRetrievesTheSection() { let testExpectation = expectation(description: "Should invoke dataSource") testExpectation.expectedFulfillmentCount = 2 let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -426,7 +459,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testResettingDataSourceDoesNotRetrieveTheSectionAgain() { + @MainActor + func testResettingDataSourceDoesNotRetrieveTheSectionAgain() { let testExpectation = expectation(description: "Should invoke dataSource") let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: { @@ -446,7 +480,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSectionsWhenThereIsASection() { + @MainActor + func testSectionsWhenThereIsASection() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let section = Section(id: "", model: "", controller: MockSectionController()) let adapter = SingleSectionCollectionViewAdapter( @@ -457,7 +492,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(adapter.sections.first === section) } - internal func testSectionsWhenThereIsNoSection() { + @MainActor + func testSectionsWhenThereIsNoSection() { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter( collectionView: collectionView, @@ -468,7 +504,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { // MARK: - calculateUpdate - internal func testCalculateUpdateFromSomeToSomeWithTheSameId() throws { + @MainActor + func testCalculateUpdateFromSomeToSomeWithTheSameId() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let update = try XCTUnwrap( @@ -486,7 +523,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromSomeToSomeWithADifferentId() throws { + @MainActor + func testCalculateUpdateFromSomeToSomeWithADifferentId() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let update = try XCTUnwrap( @@ -504,7 +542,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromNoneToSome() throws { + @MainActor + func testCalculateUpdateFromNoneToSome() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let update = try XCTUnwrap( @@ -522,7 +561,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromSomeToNone() throws { + @MainActor + func testCalculateUpdateFromSomeToNone() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let update = try XCTUnwrap( @@ -540,7 +580,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromNoneToNone() throws { + @MainActor + func testCalculateUpdateFromNoneToNone() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let update = try XCTUnwrap(adapter.calculateUpdate(from: nil, to: nil)) @@ -553,7 +594,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateHasCorrectData() throws { + @MainActor + func testCalculateUpdateHasCorrectData() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let section = Section(id: "1", model: "", controller: MockSectionController()) @@ -568,7 +610,8 @@ internal final class SingleSectionCollectionViewAdapterTests: XCTestCase { XCTAssert(batchOperation.data === section) } - internal func testCalculateUpdateSetDataSetsCollectionViewSection() throws { + @MainActor + func testCalculateUpdateSetDataSetsCollectionViewSection() throws { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let adapter = SingleSectionCollectionViewAdapter(collectionView: collectionView) let section = Section(id: "1", model: "", controller: MockSectionController()) diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/BaseCollectionViewAdapterUICollectionViewDataSourceTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/BaseCollectionViewAdapterUICollectionViewDataSourceTests.swift index 43213c35..c13c7739 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/BaseCollectionViewAdapterUICollectionViewDataSourceTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/BaseCollectionViewAdapterUICollectionViewDataSourceTests.swift @@ -2,27 +2,27 @@ import UIKit import XCTest -@MainActor -internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestCase { +class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUICollectionViewDataSourceTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } - internal func createCollectionViewAdapter( + @MainActor + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -32,7 +32,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC throw XCTSkip("Tests from base class are skipped") } - internal func testNumberOfSections() throws { + @MainActor + func testNumberOfSections() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -43,7 +44,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC XCTAssertEqual(adapter.numberOfSections?(in: collectionView), 1) } - internal func testNumberOfItemsInSection() throws { + @MainActor + func testNumberOfItemsInSection() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -62,7 +64,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC XCTAssertEqual(adapter.collectionView(collectionView, numberOfItemsInSection: 0), 1) } - internal func testNumberOfItemsInSectionWithInvalidIndex() throws { + @MainActor + func testNumberOfItemsInSectionWithInvalidIndex() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -91,7 +94,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testCellForItem() throws { + @MainActor + func testCellForItem() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -118,7 +122,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC ) } - internal func testCellForItemWithInvalidSectionIndex() throws { + @MainActor + func testCellForItemWithInvalidSectionIndex() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -155,7 +160,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testCellForItemWithInvalidIndexPath() throws { + @MainActor + func testCellForItemWithInvalidIndexPath() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -192,7 +198,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testViewForSupplementaryElementOfKindHeader() throws { + @MainActor + func testViewForSupplementaryElementOfKindHeader() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -219,7 +226,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC ) } - internal func testViewForSupplementaryElementOfKindWithInvalidSectionIndex() throws { + @MainActor + func testViewForSupplementaryElementOfKindWithInvalidSectionIndex() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -256,7 +264,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testViewForSupplementaryElementOfKindWithInvalidIndexPath() throws { + @MainActor + func testViewForSupplementaryElementOfKindWithInvalidIndexPath() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -293,7 +302,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testViewForSupplementaryElementOfKindFooter() throws { + @MainActor + func testViewForSupplementaryElementOfKindFooter() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -320,7 +330,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC ) } - internal func testViewForSupplementaryElementOfKindWithUnsupportedElementKind() throws { + @MainActor + func testViewForSupplementaryElementOfKindWithUnsupportedElementKind() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -357,7 +368,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testCanMoveItemAt() throws { + @MainActor + func testCanMoveItemAt() throws { let testExpectation = expectation(description: "Should invoke datasource") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -381,7 +393,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testMoveItemInSameSectionCallsDataSource() throws { + @MainActor + func testMoveItemInSameSectionCallsDataSource() throws { let testExpectation = expectation(description: "Should invoke datasource") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -408,7 +421,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testMoveItemInDifferentSectionNotCallsDataSource() throws { + @MainActor + func testMoveItemInDifferentSectionNotCallsDataSource() throws { let dataSourceExpectation = expectation(description: "Should not invoke datasource") dataSourceExpectation.fulfill() let errorExpectation = expectation(description: "Should invoke errorHandler") @@ -448,7 +462,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testMoveItemWithInvalidSourceIndexPath() throws { + @MainActor + func testMoveItemWithInvalidSourceIndexPath() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -470,7 +485,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } - internal func testMoveItemWithInvalidDestinationIndexPath() throws { + @MainActor + func testMoveItemWithInvalidDestinationIndexPath() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( @@ -492,15 +508,17 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourceTests: XCTestC waitForExpectations(timeout: 1) } + @MainActor @available(iOS 14.0, *) - internal func testIndexTitlesIsNil() throws { + func testIndexTitlesIsNil() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter(collectionView: collectionView) XCTAssertNil(adapter.indexTitles?(for: collectionView)) } + @MainActor @available(iOS 14.0, *) - internal func testIndexPathForIndexTitle() throws { + func testIndexPathForIndexTitle() throws { let testExpectation = expectation(description: "Should invoke errorHandler") let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/ListCollectionViewAdapterUICollectionViewDataSourceTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/ListCollectionViewAdapterUICollectionViewDataSourceTests.swift index 421c30ae..c293fd07 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/ListCollectionViewAdapterUICollectionViewDataSourceTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/ListCollectionViewAdapterUICollectionViewDataSourceTests.swift @@ -2,9 +2,9 @@ import UIKit import XCTest -@MainActor -internal final class ListCollectionViewAdapterUICollectionViewDataSourceTests: BaseCollectionViewAdapterUICollectionViewDataSourceTests { - override internal func createCollectionViewAdapter( +final class ListCollectionViewAdapterUICollectionViewDataSourceTests: BaseCollectionViewAdapterUICollectionViewDataSourceTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/SingleSectionCollectionViewAdapterUICollectionViewDataSourceTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/SingleSectionCollectionViewAdapterUICollectionViewDataSourceTests.swift index 388bb14a..077b35df 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/SingleSectionCollectionViewAdapterUICollectionViewDataSourceTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSource/SingleSectionCollectionViewAdapterUICollectionViewDataSourceTests.swift @@ -2,8 +2,8 @@ import UIKit import XCTest -@MainActor -internal final class SingleSectionCollectionViewAdapterUICollectionViewDataSourceTests: BaseCollectionViewAdapterUICollectionViewDataSourceTests { +final class SingleSectionCollectionViewAdapterUICollectionViewDataSourceTests: BaseCollectionViewAdapterUICollectionViewDataSourceTests { + @MainActor override internal func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift index 8d390447..c6c44abc 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift @@ -2,28 +2,28 @@ import UIKit import XCTest -@MainActor @available(iOS 10.0, *) -internal class BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests: XCTestCase { +class BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } - internal func createCollectionViewAdapter( + @MainActor + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -33,7 +33,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTes throw XCTSkip("Tests from base class are skipped") } - internal func testPrefetchItems() throws { + @MainActor + func testPrefetchItems() throws { let testExpectation = expectation(description: "Should invoke datasource prefetching delegate") let collectionView = createCollectionView() let itemsToPrefetch = [IndexPath(item: 0, section: 0), IndexPath(item: 1, section: 0)] @@ -58,7 +59,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTes waitForExpectations(timeout: 1) } - internal func testPrefetchItemsWithInvalidIndices() throws { + @MainActor + func testPrefetchItemsWithInvalidIndices() throws { let testExpectation = expectation(description: "Should invoke datasource prefetching delegate") let collectionView = createCollectionView() let itemsToPrefetch = [IndexPath(item: 0, section: 0), IndexPath(item: 1, section: 0)] @@ -84,7 +86,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTes waitForExpectations(timeout: 1) } - internal func testCancelPrefetchingForItems() throws { + @MainActor + func testCancelPrefetchingForItems() throws { let testExpectation = expectation(description: "Should invoke datasource prefetching delegate") let collectionView = createCollectionView() let itemsToCancel = [IndexPath(item: 0, section: 0), IndexPath(item: 1, section: 0)] @@ -109,7 +112,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTes waitForExpectations(timeout: 1) } - internal func testCancelPrefetchingForItemsWithInvalidIndices() throws { + @MainActor + func testCancelPrefetchingForItemsWithInvalidIndices() throws { let testExpectation = expectation(description: "Should invoke datasource prefetching delegate") let collectionView = createCollectionView() let itemsToCancel = [IndexPath(item: 0, section: 0), IndexPath(item: 1, section: 0)] diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift index 3907afb9..e60cb041 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift @@ -2,10 +2,10 @@ import UIKit import XCTest -@MainActor @available(iOS 10.0, *) -internal final class ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests: BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests { - override internal func createCollectionViewAdapter( +final class ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests: BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/SingleSectionCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/SingleSectionCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift index 4771a11b..5e0af08b 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/SingleSectionCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDataSourcePrefetching/SingleSectionCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift @@ -2,10 +2,10 @@ import UIKit import XCTest -@MainActor @available(iOS 10.0, *) -internal final class SingleSectionCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests: BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests { - override internal func createCollectionViewAdapter( +final class SingleSectionCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests: BaseCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/BaseCollectionViewAdapterUICollectionViewDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/BaseCollectionViewAdapterUICollectionViewDelegateTests.swift index 5ca88825..612b8407 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/BaseCollectionViewAdapterUICollectionViewDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/BaseCollectionViewAdapterUICollectionViewDelegateTests.swift @@ -2,27 +2,27 @@ import UIKit import XCTest -@MainActor -internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCase { +class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUICollectionViewDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } - internal func createCollectionViewAdapter( + @MainActor + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -32,7 +32,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas throw XCTSkip("Tests from base class are skipped") } - internal func testShouldHighlightItem() throws { + @MainActor + func testShouldHighlightItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -61,7 +62,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testShouldHighlightItemWithoutDelegate() throws { + @MainActor + func testShouldHighlightItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -80,7 +82,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testDidHighlightItem() throws { + @MainActor + func testDidHighlightItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -105,7 +108,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidHighlightItemWithoutDelegate() throws { + @MainActor + func testDidHighlightItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -121,7 +125,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionView?(collectionView, didHighlightItemAt: itemIndexPath.indexInCollectionView) } - internal func testDidUnhighlightItem() throws { + @MainActor + func testDidUnhighlightItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -146,7 +151,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidUnhighlightItemWithoutDelegate() throws { + @MainActor + func testDidUnhighlightItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -162,7 +168,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionView?(collectionView, didUnhighlightItemAt: itemIndexPath.indexInCollectionView) } - internal func testShouldSelectItem() throws { + @MainActor + func testShouldSelectItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -191,7 +198,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testShouldSelectItemWithoutDelegate() throws { + @MainActor + func testShouldSelectItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -210,7 +218,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testShouldDeselectItem() throws { + @MainActor + func testShouldDeselectItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -239,7 +248,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testShouldDeselectItemWithoutDelegate() throws { + @MainActor + func testShouldDeselectItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -258,7 +268,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testDidSelectItem() throws { + @MainActor + func testDidSelectItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -283,7 +294,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidSelectItemWithoutDelegate() throws { + @MainActor + func testDidSelectItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -299,7 +311,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionView?(collectionView, didSelectItemAt: itemIndexPath.indexInCollectionView) } - internal func testDidDeselectItem() throws { + @MainActor + func testDidDeselectItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -324,7 +337,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidDeselectItemWithoutDelegate() throws { + @MainActor + func testDidDeselectItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -340,7 +354,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionView?(collectionView, didDeselectItemAt: itemIndexPath.indexInCollectionView) } - internal func testWillDisplayCell() throws { + @MainActor + func testWillDisplayCell() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -367,7 +382,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testWillDisplayCellWithoutDelegate() throws { + @MainActor + func testWillDisplayCellWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let itemCell = MockCollectionViewCell() @@ -384,7 +400,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionView?(collectionView, willDisplay: itemCell, forItemAt: itemIndexPath.indexInCollectionView) } - internal func testWillDisplayHeaderView() throws { + @MainActor + func testWillDisplayHeaderView() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -416,7 +433,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testWillDisplayFooterView() throws { + @MainActor + func testWillDisplayFooterView() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -448,7 +466,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testWillDisplaySupplementaryViewWithoutDelegate() throws { + @MainActor + func testWillDisplaySupplementaryViewWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let itemHeaderView = MockCollectionReusableView() @@ -470,7 +489,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testWillDisplaySupplementaryViewWithInvalidElementKind() throws { + @MainActor + func testWillDisplaySupplementaryViewWithInvalidElementKind() throws { let delegateExpectation = expectation(description: "Should not invoke delegate") delegateExpectation.fulfill() let errorExpectation = expectation(description: "Should invoke errorHandler") @@ -513,7 +533,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidEndDisplayingCell() throws { + @MainActor + func testDidEndDisplayingCell() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -540,7 +561,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidEndDisplayingCellWithoutDelegate() throws { + @MainActor + func testDidEndDisplayingCellWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let itemCell = MockCollectionViewCell() @@ -557,7 +579,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionView?(collectionView, didEndDisplaying: itemCell, forItemAt: itemIndexPath.indexInCollectionView) } - internal func testDidEndDisplayingHeaderView() throws { + @MainActor + func testDidEndDisplayingHeaderView() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -589,7 +612,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidEndDisplayingFooterView() throws { + @MainActor + func testDidEndDisplayingFooterView() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -621,7 +645,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testDidEndDisplayingSupplementaryViewWithoutDelegate() throws { + @MainActor + func testDidEndDisplayingSupplementaryViewWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let itemHeaderView = MockCollectionReusableView() @@ -643,7 +668,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testDidEndDisplayingSupplementaryWithInvalidElementKind() throws { + @MainActor + func testDidEndDisplayingSupplementaryWithInvalidElementKind() throws { let delegateExpectation = expectation(description: "Should not invoke delegate") delegateExpectation.fulfill() let errorExpectation = expectation(description: "Should invoke errorHandler") @@ -687,8 +713,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testShouldShowMenuForItem() throws { + func testShouldShowMenuForItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -718,8 +745,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testShouldShowMenuForItemWithoutDelegate() throws { + func testShouldShowMenuForItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -739,8 +767,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testCanPerform() throws { + func testCanPerform() throws { class Mock { @objc func perform() { } @@ -782,8 +811,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testCanPerformWithoutDelegate() throws { + func testCanPerformWithoutDelegate() throws { class Mock { @objc func perform() { } @@ -813,8 +843,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testPerform() throws { + func testPerform() throws { class Mock { @objc func perform() { } @@ -852,8 +883,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testPerformWithoutDelegate() throws { + func testPerformWithoutDelegate() throws { class Mock { @objc func perform() { } @@ -879,7 +911,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testTransitionLayoutForOldLayout() throws { + @MainActor + func testTransitionLayoutForOldLayout() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -900,7 +933,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas XCTAssert(transitionLayout.nextLayout === toLayout) } - internal func testCanFocusItem() throws { + @MainActor + func testCanFocusItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -929,7 +963,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } - internal func testCanFocusItemWithoutDelegate() throws { + @MainActor + func testCanFocusItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -949,7 +984,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas } // Not possible to instantiate `UICollectionViewFocusUpdateContext` -// internal func testShouldUpdateFocus() throws { +// func testShouldUpdateFocus() throws { // let collectionView = createCollectionView() // let adapter = try createCollectionViewAdapter( // collectionView: collectionView, @@ -964,7 +999,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas // } // Not possible to instantiate `UICollectionViewFocusUpdateContext` -// internal func testDidUpdateFocus() throws { +// func testDidUpdateFocus() throws { // let collectionView = createCollectionView() // let adapter = try createCollectionViewAdapter( // collectionView: collectionView, @@ -979,7 +1014,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas // ) // } - internal func testIndexPathForPreferredFocusedView() throws { + @MainActor + func testIndexPathForPreferredFocusedView() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -990,7 +1026,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas XCTAssertNil(adapter.indexPathForPreferredFocusedView?(in: collectionView)) } - internal func testTargetIndexPathForMoveFromItem() throws { + @MainActor + func testTargetIndexPathForMoveFromItem() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -1010,7 +1047,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } - internal func testTargetContentOffsetForProposedContentOffset() throws { + @MainActor + func testTargetContentOffsetForProposedContentOffset() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -1028,8 +1066,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 11.0, *) - internal func testShouldSpringLoadItem() throws { + func testShouldSpringLoadItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -1064,8 +1103,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } + @MainActor @available(iOS 11.0, *) - internal func testShouldSpringLoadItemWithoutDelegate() throws { + func testShouldSpringLoadItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let mockContext = MockSpringLoadedInteractionContext() @@ -1089,8 +1129,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 13.0, *) - internal func testShouldBeginMultipleSelectionInteraction() throws { + func testShouldBeginMultipleSelectionInteraction() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -1122,8 +1163,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } + @MainActor @available(iOS 13.0, *) - internal func testShouldBeginMultipleSelectionInteractionWithoutDelegate() throws { + func testShouldBeginMultipleSelectionInteractionWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -1145,8 +1187,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 13.0, *) - internal func testDidBeginMultipleSelectionInteraction() throws { + func testDidBeginMultipleSelectionInteraction() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -1174,8 +1217,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } + @MainActor @available(iOS 13.0, *) - internal func testDidBeginMultipleSelectionInteractionWithoutDelegate() throws { + func testDidBeginMultipleSelectionInteractionWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let adapter = try createCollectionViewAdapter( @@ -1194,8 +1238,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 13.0, *) - internal func testDidEndMultipleSelectionInteraction() throws { + func testDidEndMultipleSelectionInteraction() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -1206,8 +1251,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas adapter.collectionViewDidEndMultipleSelectionInteraction?(collectionView) } + @MainActor @available(iOS 13.0, *) - internal func testContextMenuConfigurationForItem() throws { + func testContextMenuConfigurationForItem() throws { let testExpectation = expectation(description: "Should invoke delegate") let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) @@ -1242,8 +1288,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas waitForExpectations(timeout: 1) } + @MainActor @available(iOS 13.0, *) - internal func testContextMenuConfigurationForItemWithoutDelegate() throws { + func testContextMenuConfigurationForItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = SectionIndexPath(IndexPath(item: 0, section: 0)) let itemPoint = CGPoint(x: 1, y: 2) @@ -1266,8 +1313,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 13.0, *) - internal func testPreviewForHighlightingContextMenuWithConfiguration() throws { + func testPreviewForHighlightingContextMenuWithConfiguration() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -1283,8 +1331,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 13.0, *) - internal func testPreviewForDismissingContextMenuWithConfiguration() throws { + func testPreviewForDismissingContextMenuWithConfiguration() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, @@ -1300,8 +1349,9 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateTests: XCTestCas ) } + @MainActor @available(iOS 13.0, *) - internal func testWillPerformPreviewActionForMenu() throws { + func testWillPerformPreviewActionForMenu() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/ListCollectionViewAdapterUICollectionViewDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/ListCollectionViewAdapterUICollectionViewDelegateTests.swift index 65df0d45..ce8d315c 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/ListCollectionViewAdapterUICollectionViewDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/ListCollectionViewAdapterUICollectionViewDelegateTests.swift @@ -2,8 +2,8 @@ import UIKit import XCTest -@MainActor -internal final class ListCollectionViewAdapterUICollectionViewDelegateTests: BaseCollectionViewAdapterUICollectionViewDelegateTests { +final class ListCollectionViewAdapterUICollectionViewDelegateTests: BaseCollectionViewAdapterUICollectionViewDelegateTests { + @MainActor override internal func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/SingleSectionCollectionViewAdapterUICollectionViewDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/SingleSectionCollectionViewAdapterUICollectionViewDelegateTests.swift index e81dd5f6..b02f27af 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/SingleSectionCollectionViewAdapterUICollectionViewDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegate/SingleSectionCollectionViewAdapterUICollectionViewDelegateTests.swift @@ -2,8 +2,8 @@ import UIKit import XCTest -@MainActor -internal final class SingleSectionCollectionViewAdapterUICollectionViewDelegateTests: BaseCollectionViewAdapterUICollectionViewDelegateTests { +final class SingleSectionCollectionViewAdapterUICollectionViewDelegateTests: BaseCollectionViewAdapterUICollectionViewDelegateTests { + @MainActor override internal func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift index c8049f1d..9f742de6 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift @@ -2,9 +2,9 @@ import UIKit import XCTest -@MainActor -internal final class SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests { - override internal func createCollectionViewAdapter( +final class SingleSectionCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/BaseCollectionViewAdapterUICollectionViewDragDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/BaseCollectionViewAdapterUICollectionViewDragDelegateTests.swift index 5206be14..884141c1 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/BaseCollectionViewAdapterUICollectionViewDragDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/BaseCollectionViewAdapterUICollectionViewDragDelegateTests.swift @@ -2,28 +2,28 @@ import UIKit import XCTest -@MainActor @available(iOS 11.0, *) -internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTestCase { +class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUICollectionViewDragDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } - internal func createCollectionViewAdapter( + @MainActor + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -35,7 +35,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - itemsForBeginning - internal func testItemsForBeginningWithDelegate() throws { + @MainActor + func testItemsForBeginningWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drag delegate") let collectionView = createCollectionView() let mockSession = MockDragSession() @@ -70,7 +71,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testItemsForBeginningWithoutDelegate() throws { + @MainActor + func testItemsForBeginningWithoutDelegate() throws { let collectionView = createCollectionView() let mockSession = MockDragSession() let itemIndexPath = IndexPath(item: 0, section: 0) @@ -93,7 +95,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - itemsForAdding - internal func testItemsForAddingWithDelegate() throws { + @MainActor + func testItemsForAddingWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drag delegate") let collectionView = createCollectionView() let mockSession = MockDragSession() @@ -131,7 +134,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testItemsForAddingWithoutDelegate() throws { + @MainActor + func testItemsForAddingWithoutDelegate() throws { let collectionView = createCollectionView() let mockSession = MockDragSession() let itemIndexPath = IndexPath(item: 0, section: 0) @@ -159,7 +163,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - dragPreviewParametersForItem - internal func testDragPreviewParametersForItemWithDelegate() throws { + @MainActor + func testDragPreviewParametersForItemWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drag delegate") let collectionView = createCollectionView() let itemIndexPath = IndexPath(item: 0, section: 0) @@ -191,7 +196,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDragPreviewParametersForItemWithoutDelegate() throws { + @MainActor + func testDragPreviewParametersForItemWithoutDelegate() throws { let collectionView = createCollectionView() let itemIndexPath = IndexPath(item: 0, section: 0) let adapter = try createCollectionViewAdapter( @@ -214,7 +220,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - dragSessionWillBegin - internal func testDragSessionWillBegin() throws { + @MainActor + func testDragSessionWillBegin() throws { let testExpectation = expectation(description: "Should invoke drag delegate") let collectionView = createCollectionView() let mockSession = MockDragSession() @@ -244,7 +251,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - dragSessionDidEnd - internal func testDragSessionDidEnd() throws { + @MainActor + func testDragSessionDidEnd() throws { let testExpectation = expectation(description: "Should invoke drag delegate") let collectionView = createCollectionView() let mockSession = MockDragSession() @@ -274,7 +282,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - dragSessionAllowsMoveOperation - internal func testDragSessionAllowsMoveOperation() throws { + @MainActor + func testDragSessionAllowsMoveOperation() throws { let collectionView = createCollectionView() let mockSession = MockDragSession() let adapter = try createCollectionViewAdapter( @@ -291,7 +300,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDragDelegateTests: XCTes // MARK: - dragSessionIsRestrictedToDraggingApplication - internal func testDragSessionIsRestrictedToDraggingApplication() throws { + @MainActor + func testDragSessionIsRestrictedToDraggingApplication() throws { let collectionView = createCollectionView() let mockSession = MockDragSession() let adapter = try createCollectionViewAdapter( diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/SingleSectionCollectionViewAdapterUICollectionViewDragDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/SingleSectionCollectionViewAdapterUICollectionViewDragDelegateTests.swift index c8c152b2..d78751cc 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/SingleSectionCollectionViewAdapterUICollectionViewDragDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDragDelegate/SingleSectionCollectionViewAdapterUICollectionViewDragDelegateTests.swift @@ -2,10 +2,10 @@ import UIKit import XCTest -@MainActor @available(iOS 11.0, *) -internal final class SingleSectionCollectionViewAdapterUICollectionViewDragDelegateTests: BaseCollectionViewAdapterUICollectionViewDragDelegateTests { - override internal func createCollectionViewAdapter( +final class SingleSectionCollectionViewAdapterUICollectionViewDragDelegateTests: BaseCollectionViewAdapterUICollectionViewDragDelegateTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/BaseCollectionViewAdapterUICollectionViewDropDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/BaseCollectionViewAdapterUICollectionViewDropDelegateTests.swift index 43524efe..1050d07a 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/BaseCollectionViewAdapterUICollectionViewDropDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/BaseCollectionViewAdapterUICollectionViewDropDelegateTests.swift @@ -2,28 +2,28 @@ import UIKit import XCTest -@MainActor @available(iOS 11.0, *) -internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTestCase { +class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUICollectionViewDropDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } - internal func createCollectionViewAdapter( + @MainActor + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -35,7 +35,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - canHandle - internal func testCanHandleWithDelegate() throws { + @MainActor + func testCanHandleWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let collectionView = createCollectionView() let mockSession = MockDropSession() @@ -64,7 +65,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testCanHandleWithoutDelegate() throws { + @MainActor + func testCanHandleWithoutDelegate() throws { let collectionView = createCollectionView() let mockSession = MockDropSession() let adapter = try createCollectionViewAdapter( @@ -85,7 +87,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - dropSessionDidUpdate - internal func testDropSessionDidUpdateWithDestinationIndexPathAndWithInvalidIndex() throws { + @MainActor + func testDropSessionDidUpdateWithDestinationIndexPathAndWithInvalidIndex() throws { let testExpectation = expectation(description: "Should not invoke drop delegate") testExpectation.fulfill() let collectionView = createCollectionView() @@ -119,7 +122,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDropSessionDidUpdateWithDestinationIndexPathAndWithDelegate() throws { + @MainActor + func testDropSessionDidUpdateWithDestinationIndexPathAndWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let collectionView = createCollectionView() let mockSession = MockDropSession() @@ -154,7 +158,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDropSessionDidUpdateWithDestinationIndexPathAndWithoutDelegate() throws { + @MainActor + func testDropSessionDidUpdateWithDestinationIndexPathAndWithoutDelegate() throws { let collectionView = createCollectionView() let mockSession = MockDropSession() let indexPath = IndexPath(item: 0, section: 0) @@ -178,7 +183,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes ) } - internal func testDropSessionDidUpdateWithoutDestinationIndexPathAndWithDelegate() throws { + @MainActor + func testDropSessionDidUpdateWithoutDestinationIndexPathAndWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) collectionView._indexPathForItem = { _ in IndexPath(item: 0, section: 0) } @@ -213,7 +219,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDropSessionDidUpdateWithoutDestinationIndexPathButInvalidLocation() throws { + @MainActor + func testDropSessionDidUpdateWithoutDestinationIndexPathButInvalidLocation() throws { let testExpectation = expectation(description: "Should invoke indexPathForItem") let mockPoint = CGPoint(x: 1, y: 2) let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -241,7 +248,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDropSessionDidUpdateWithoutDestinationIndexPathButLocationOfInvalidIndexPath() throws { + @MainActor + func testDropSessionDidUpdateWithoutDestinationIndexPathButLocationOfInvalidIndexPath() throws { let testExpectation = expectation(description: "Should invoke indexPathForItem") let mockPoint = CGPoint(x: 1, y: 2) let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -269,7 +277,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDropSessionDidUpdateWithoutDestinationIndexPathAndWithoutDelegate() throws { + @MainActor + func testDropSessionDidUpdateWithoutDestinationIndexPathAndWithoutDelegate() throws { let testExpectation = expectation(description: "Should invoke indexPathForItem") let mockPoint = CGPoint(x: 1, y: 2) let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) @@ -303,7 +312,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - performDrop - internal func testPerformDropWithoutDestinationIndexPath() throws { + @MainActor + func testPerformDropWithoutDestinationIndexPath() throws { let testExpectation = expectation(description: "Should not invoke drop delegate") testExpectation.fulfill() let coordinator = MockCollectionViewDropCoordinator() @@ -329,7 +339,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testPerformDropWithInvalidDestinationIndexPath() throws { + @MainActor + func testPerformDropWithInvalidDestinationIndexPath() throws { let testExpectation = expectation(description: "Should not invoke drop delegate") testExpectation.fulfill() let coordinator = MockCollectionViewDropCoordinator() @@ -355,7 +366,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testPerformDropWithUnknownDestinationIndexPath() throws { + @MainActor + func testPerformDropWithUnknownDestinationIndexPath() throws { let testExpectation = expectation(description: "Should not invoke drop delegate") testExpectation.fulfill() let coordinator = MockCollectionViewDropCoordinator() @@ -381,7 +393,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testPerformDropFromDifferentLocalSection() throws { + @MainActor + func testPerformDropFromDifferentLocalSection() throws { let testExpectation = expectation(description: "Should not invoke drop delegate") testExpectation.fulfill() let coordinator = MockCollectionViewDropCoordinator() @@ -414,7 +427,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testPerformDropFromSameLocalSection() throws { + @MainActor + func testPerformDropFromSameLocalSection() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let coordinator = MockCollectionViewDropCoordinator() coordinator.destinationIndexPath = IndexPath(item: 0, section: 0) @@ -446,7 +460,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testPerformDropFromRemote() throws { + @MainActor + func testPerformDropFromRemote() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let coordinator = MockCollectionViewDropCoordinator() coordinator.destinationIndexPath = IndexPath(item: 0, section: 0) @@ -474,7 +489,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testPerformDropWithoutDelegate() throws { + @MainActor + func testPerformDropWithoutDelegate() throws { let coordinator = MockCollectionViewDropCoordinator() coordinator.destinationIndexPath = IndexPath(item: 0, section: 0) let collectionView = createCollectionView() @@ -493,7 +509,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - dropSessionDidEnter - internal func testDropSessionDidEnter() throws { + @MainActor + func testDropSessionDidEnter() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let mockSession = MockDropSession() let collectionView = createCollectionView() @@ -520,7 +537,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - dropSessionDidExit - internal func testDropSessionDidExit() throws { + @MainActor + func testDropSessionDidExit() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let mockSession = MockDropSession() let collectionView = createCollectionView() @@ -547,7 +565,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - dropSessionDidEnd - internal func testDropSessionDidEnd() throws { + @MainActor + func testDropSessionDidEnd() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let mockSession = MockDropSession() let collectionView = createCollectionView() @@ -574,7 +593,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes // MARK: - dropPreviewParametersForItem - internal func testDropPreviewParametersForItemWithDelegate() throws { + @MainActor + func testDropPreviewParametersForItemWithDelegate() throws { let testExpectation = expectation(description: "Should invoke drop delegate") let itemIndexPath = IndexPath(item: 0, section: 0) let mockPreviewParameters = UIDragPreviewParameters() @@ -606,7 +626,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDropDelegateTests: XCTes waitForExpectations(timeout: 1) } - internal func testDropPreviewParametersForItemWithoutDelegate() throws { + @MainActor + func testDropPreviewParametersForItemWithoutDelegate() throws { let collectionView = createCollectionView() let adapter = try createCollectionViewAdapter( collectionView: collectionView, diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/ListCollectionViewAdapterUICollectionViewDropDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/ListCollectionViewAdapterUICollectionViewDropDelegateTests.swift index 10875847..d7b9a531 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/ListCollectionViewAdapterUICollectionViewDropDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/ListCollectionViewAdapterUICollectionViewDropDelegateTests.swift @@ -2,9 +2,9 @@ import UIKit import XCTest -@MainActor @available(iOS 11.0, *) -internal final class ListCollectionViewAdapterUICollectionViewDropDelegateTests: BaseCollectionViewAdapterUICollectionViewDropDelegateTests { +final class ListCollectionViewAdapterUICollectionViewDropDelegateTests: BaseCollectionViewAdapterUICollectionViewDropDelegateTests { + @MainActor override internal func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/SingleSectionCollectionViewAdapterUICollectionViewDropDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/SingleSectionCollectionViewAdapterUICollectionViewDropDelegateTests.swift index 7b6bf72f..3ec3590e 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/SingleSectionCollectionViewAdapterUICollectionViewDropDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDropDelegate/SingleSectionCollectionViewAdapterUICollectionViewDropDelegateTests.swift @@ -2,10 +2,10 @@ import UIKit import XCTest -@MainActor @available(iOS 11.0, *) -internal final class SingleSectionCollectionViewAdapterUICollectionViewDropDelegateTests: BaseCollectionViewAdapterUICollectionViewDropDelegateTests { - override internal func createCollectionViewAdapter( +final class SingleSectionCollectionViewAdapterUICollectionViewDropDelegateTests: BaseCollectionViewAdapterUICollectionViewDropDelegateTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/BaseCollectionViewAdapterUIScrollViewDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/BaseCollectionViewAdapterUIScrollViewDelegateTests.swift index 203e881a..96eff4d0 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/BaseCollectionViewAdapterUIScrollViewDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/BaseCollectionViewAdapterUIScrollViewDelegateTests.swift @@ -2,27 +2,27 @@ import UIKit import XCTest -@MainActor -internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { +class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUIScrollViewDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { UICollectionView(frame: frame, collectionViewLayout: layout ?? UICollectionViewFlowLayout()) } - internal func createCollectionViewAdapter( + @MainActor + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -32,7 +32,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { throw XCTSkip("Tests from base class are skipped") } - internal func testScrollViewDidScroll() throws { + @MainActor + func testScrollViewDidScroll() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -48,7 +49,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewDidZoom() throws { + @MainActor + func testScrollViewDidZoom() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -64,7 +66,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewWillBeginDragging() throws { + @MainActor + func testScrollViewWillBeginDragging() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -80,7 +83,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewWillEndDragging() throws { + @MainActor + func testScrollViewWillEndDragging() throws { let velocity = CGPoint(x: 1, y: 2) let targetContentOffset = CGPoint(x: 4, y: 8) let testExpectation = expectation(description: "Should invoke scroll delegate") @@ -105,7 +109,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewDidEndDragging() throws { + @MainActor + func testScrollViewDidEndDragging() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -122,7 +127,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewWillBeginDecelerating() throws { + @MainActor + func testScrollViewWillBeginDecelerating() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -138,7 +144,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewDidEndDecelerating() throws { + @MainActor + func testScrollViewDidEndDecelerating() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -154,7 +161,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewDidEndScrollingAnimation() throws { + @MainActor + func testScrollViewDidEndScrollingAnimation() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -170,7 +178,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testViewForZooming() throws { + @MainActor + func testViewForZooming() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -188,7 +197,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewWillBeginZooming() throws { + @MainActor + func testScrollViewWillBeginZooming() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -206,7 +216,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewDidEndZooming() throws { + @MainActor + func testScrollViewDidEndZooming() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -225,7 +236,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewShouldScrollToTop() throws { + @MainActor + func testScrollViewShouldScrollToTop() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -242,7 +254,8 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testScrollViewDidScrollToTop() throws { + @MainActor + func testScrollViewDidScrollToTop() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() @@ -258,8 +271,9 @@ internal class BaseCollectionViewAdapterUIScrollViewDelegateTests: XCTestCase { waitForExpectations(timeout: 1) } + @MainActor @available(iOS 11.0, *) - internal func testScrollViewDidChangeAdjustedContentInset() throws { + func testScrollViewDidChangeAdjustedContentInset() throws { let testExpectation = expectation(description: "Should invoke scroll delegate") let collectionView = createCollectionView() let scrollViewDelegate = MockScrollViewDelegate() diff --git a/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/ListCollectionViewAdapterUIScrollViewDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/ListCollectionViewAdapterUIScrollViewDelegateTests.swift index 6fce48ab..3ea28e10 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/ListCollectionViewAdapterUIScrollViewDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/ListCollectionViewAdapterUIScrollViewDelegateTests.swift @@ -2,9 +2,9 @@ import UIKit import XCTest -@MainActor -internal final class ListCollectionViewAdapterUIScrollViewDelegateTests: BaseCollectionViewAdapterUIScrollViewDelegateTests { - override internal func createCollectionViewAdapter( +final class ListCollectionViewAdapterUIScrollViewDelegateTests: BaseCollectionViewAdapterUIScrollViewDelegateTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/SingleSectionCollectionViewAdapterUIScrollViewDelegateTests.swift b/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/SingleSectionCollectionViewAdapterUIScrollViewDelegateTests.swift index eb321b1f..3790036d 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/SingleSectionCollectionViewAdapterUIScrollViewDelegateTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UIScrollViewDelegate/SingleSectionCollectionViewAdapterUIScrollViewDelegateTests.swift @@ -2,9 +2,9 @@ import UIKit import XCTest -@MainActor -internal final class SingleSectionCollectionViewAdapterUIScrollViewDelegateTests: BaseCollectionViewAdapterUIScrollViewDelegateTests { - override internal func createCollectionViewAdapter( +final class SingleSectionCollectionViewAdapterUIScrollViewDelegateTests: BaseCollectionViewAdapterUIScrollViewDelegateTests { + @MainActor + override func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, diff --git a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift index 7598ce13..0577bf6b 100644 --- a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift @@ -1,42 +1,48 @@ import SectionKit import XCTest -@MainActor -internal final class BaseSectionControllerTests: XCTestCase { - internal func testContextIsNil() { +final class BaseSectionControllerTests: XCTestCase { + @MainActor + func testContextIsNil() { let sectionController = BaseSectionController() XCTAssertNil(sectionController.context) } - internal func testDataSourceIsSelf() { + @MainActor + func testDataSourceIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.dataSource === sectionController) } + @MainActor @available(iOS 10.0, *) - internal func testDataSourcePrefetchingDelegateIsSelf() { + func testDataSourcePrefetchingDelegateIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.dataSourcePrefetchingDelegate === sectionController) } - internal func testDelegateIsSelf() { + @MainActor + func testDelegateIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.delegate === sectionController) } @available(iOS 11.0, *) - internal func testDragDelegateIsSelf() { + @MainActor + func testDragDelegateIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.dragDelegate === sectionController) } + @MainActor @available(iOS 11.0, *) - internal func testDropDelegateIsSelf() { + func testDropDelegateIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.dropDelegate === sectionController) } - internal func testDidUpdateModelDoesNothing() { + @MainActor + func testDidUpdateModelDoesNothing() { let sectionController = BaseSectionController() sectionController.didUpdate(model: "") } diff --git a/SectionKit/Tests/SectionController/ListSectionControllerTests.swift b/SectionKit/Tests/SectionController/ListSectionControllerTests.swift index 4aa22352..be716a84 100644 --- a/SectionKit/Tests/SectionController/ListSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/ListSectionControllerTests.swift @@ -1,15 +1,16 @@ @testable import SectionKit import XCTest -@MainActor -internal final class ListSectionControllerTests: XCTestCase { - internal func testDidUpdateModelWithValidTypeSetsModel() { +final class ListSectionControllerTests: XCTestCase { + @MainActor + func testDidUpdateModelWithValidTypeSetsModel() { let sectionController = ListSectionController(model: "1") sectionController.didUpdate(model: "2") XCTAssertEqual(sectionController.model, "2") } - internal func testDidUpdateModelWithInvalidType() { + @MainActor + func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionController = ListSectionController(model: "1") let context = MainCollectionViewContext( @@ -32,7 +33,8 @@ internal final class ListSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testInitDoesNotUpdateItemsIfShouldNotUpdateItems() { + @MainActor + func testInitDoesNotUpdateItemsIfShouldNotUpdateItems() { class TestSectionController: ListSectionController { var itemsForModelExpectation: XCTestExpectation? @@ -56,7 +58,8 @@ internal final class ListSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSettingModelDoesNotUpdateItemsIfShouldNotUpdateItems() { + @MainActor + func testSettingModelDoesNotUpdateItemsIfShouldNotUpdateItems() { class TestSectionController: ListSectionController { var itemsForModelExpectation: XCTestExpectation? @@ -83,12 +86,14 @@ internal final class ListSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testShouldUpdateItemsDefaultsToTrue() { + @MainActor + func testShouldUpdateItemsDefaultsToTrue() { let sectionController = ListSectionController(model: "1") XCTAssert(sectionController.shouldUpdateItems(afterModelChangedTo: "2")) } - internal func testItemsForModelInvokesNotImplementedError() { + @MainActor + func testItemsForModelInvokesNotImplementedError() { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionController = ListSectionController(model: "1") let context = MainCollectionViewContext( @@ -108,7 +113,8 @@ internal final class ListSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testNumberOfItems() { + @MainActor + func testNumberOfItems() { let sectionController = ListSectionController(model: "1") sectionController.items = ["1", "2"] let context = MainCollectionViewContext( diff --git a/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionControllerSectionDataSourceTests.swift b/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionControllerSectionDataSourceTests.swift index ec0b8ca3..39630800 100644 --- a/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionControllerSectionDataSourceTests.swift +++ b/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionControllerSectionDataSourceTests.swift @@ -1,8 +1,8 @@ import SectionKit import XCTest -@MainActor -internal final class BaseSectionControllerSectionDataSourceTests: BaseSectionDataSourceTests { +final class BaseSectionControllerSectionDataSourceTests: BaseSectionDataSourceTests { + @MainActor override func createSectionDataSource() throws -> SectionDataSource { BaseSectionController() } diff --git a/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionDataSourceTests.swift b/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionDataSourceTests.swift index a27e3c49..721334c8 100644 --- a/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionDataSourceTests.swift +++ b/SectionKit/Tests/SectionController/SectionDataSource/BaseSectionDataSourceTests.swift @@ -1,24 +1,25 @@ import SectionKit import XCTest -@MainActor -internal class BaseSectionDataSourceTests: XCTestCase { +class BaseSectionDataSourceTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseSectionDataSourceTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createSectionDataSource() throws -> SectionDataSource { + @MainActor + func createSectionDataSource() throws -> SectionDataSource { throw XCTSkip("Tests from base class are skipped") } - internal func testNumberOfItems() throws { + @MainActor + func testNumberOfItems() throws { let sectionDataSource = try createSectionDataSource() let context = MainCollectionViewContext( viewController: nil, @@ -28,7 +29,8 @@ internal class BaseSectionDataSourceTests: XCTestCase { XCTAssertEqual(sectionDataSource.numberOfItems(in: context), 0) } - internal func testCellForItem() throws { + @MainActor + func testCellForItem() throws { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionDataSource = try createSectionDataSource() let context = MainCollectionViewContext( @@ -54,7 +56,8 @@ internal class BaseSectionDataSourceTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testHeaderView() throws { + @MainActor + func testHeaderView() throws { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionDataSource = try createSectionDataSource() let context = MainCollectionViewContext( @@ -80,7 +83,8 @@ internal class BaseSectionDataSourceTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testFooterView() throws { + @MainActor + func testFooterView() throws { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionDataSource = try createSectionDataSource() let context = MainCollectionViewContext( @@ -106,7 +110,8 @@ internal class BaseSectionDataSourceTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testCanMoveItem() throws { + @MainActor + func testCanMoveItem() throws { let sectionDataSource = try createSectionDataSource() let context = MainCollectionViewContext( viewController: nil, @@ -117,7 +122,8 @@ internal class BaseSectionDataSourceTests: XCTestCase { XCTAssertFalse(sectionDataSource.canMoveItem(at: indexPath, in: context)) } - internal func testMoveItem() throws { + @MainActor + func testMoveItem() throws { let sectionDataSource = try createSectionDataSource() let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/SectionController/SectionDataSource/ProtocolDefaultValuesSectionDataSourceTests.swift b/SectionKit/Tests/SectionController/SectionDataSource/ProtocolDefaultValuesSectionDataSourceTests.swift index 26439d23..ea2450b3 100644 --- a/SectionKit/Tests/SectionController/SectionDataSource/ProtocolDefaultValuesSectionDataSourceTests.swift +++ b/SectionKit/Tests/SectionController/SectionDataSource/ProtocolDefaultValuesSectionDataSourceTests.swift @@ -1,8 +1,8 @@ import SectionKit import XCTest -@MainActor -internal final class ProtocolDefaultValuesSectionDataSourceTests: BaseSectionDataSourceTests { +final class ProtocolDefaultValuesSectionDataSourceTests: BaseSectionDataSourceTests { + @MainActor override func createSectionDataSource() throws -> SectionDataSource { class DefaultSectionDataSource: SectionDataSource { func numberOfItems(in context: CollectionViewContext) -> Int { diff --git a/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionControllerSectionDataSourcePrefetchingDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionControllerSectionDataSourcePrefetchingDelegateTests.swift index 84096c71..f7ca5f05 100644 --- a/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionControllerSectionDataSourcePrefetchingDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionControllerSectionDataSourcePrefetchingDelegateTests.swift @@ -1,9 +1,9 @@ import SectionKit import XCTest -@MainActor @available(iOS 10.0, *) -internal final class BaseSectionControllerSectionDataSourcePrefetchingDelegateTests: BaseSectionDataSourcePrefetchingDelegateTests { +final class BaseSectionControllerSectionDataSourcePrefetchingDelegateTests: BaseSectionDataSourcePrefetchingDelegateTests { + @MainActor override func createSectionDataSourcePrefetchingDelegate() throws -> SectionDataSourcePrefetchingDelegate { BaseSectionController() } diff --git a/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionDataSourcePrefetchingDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionDataSourcePrefetchingDelegateTests.swift index 52db69de..d33993e1 100644 --- a/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionDataSourcePrefetchingDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/BaseSectionDataSourcePrefetchingDelegateTests.swift @@ -1,25 +1,26 @@ import SectionKit import XCTest -@MainActor @available(iOS 10.0, *) -internal class BaseSectionDataSourcePrefetchingDelegateTests: XCTestCase { +class BaseSectionDataSourcePrefetchingDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseSectionDataSourcePrefetchingDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createSectionDataSourcePrefetchingDelegate() throws -> SectionDataSourcePrefetchingDelegate { + @MainActor + func createSectionDataSourcePrefetchingDelegate() throws -> SectionDataSourcePrefetchingDelegate { throw XCTSkip("Tests from base class are skipped") } - internal func testPrefetchItems() throws { + @MainActor + func testPrefetchItems() throws { let sectionDataSourcePrefetchingDelegate = try createSectionDataSourcePrefetchingDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -29,7 +30,8 @@ internal class BaseSectionDataSourcePrefetchingDelegateTests: XCTestCase { sectionDataSourcePrefetchingDelegate.prefetchItems(at: [], in: context) } - internal func testCancelPrefetchingForItems() throws { + @MainActor + func testCancelPrefetchingForItems() throws { let sectionDataSourcePrefetchingDelegate = try createSectionDataSourcePrefetchingDelegate() let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests.swift index 2a7e2c49..25d2d4fc 100644 --- a/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDataSourcePrefetchingDelegate/ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests.swift @@ -1,9 +1,9 @@ import SectionKit import XCTest -@MainActor @available(iOS 10.0, *) -internal final class ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests: BaseSectionDataSourcePrefetchingDelegateTests { +final class ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests: BaseSectionDataSourcePrefetchingDelegateTests { + @MainActor override func createSectionDataSourcePrefetchingDelegate() throws -> SectionDataSourcePrefetchingDelegate { class DefaultSectionDataSourcePrefetchingDelegate: SectionDataSourcePrefetchingDelegate { func prefetchItems(at indexPaths: [SectionIndexPath], in context: CollectionViewContext) { } diff --git a/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionControllerSectionDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionControllerSectionDelegateTests.swift index fa3e5011..4a865224 100644 --- a/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionControllerSectionDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionControllerSectionDelegateTests.swift @@ -1,8 +1,8 @@ import SectionKit import XCTest -@MainActor -internal final class BaseSectionControllerSectionDelegateTests: BaseSectionDelegateTests { +final class BaseSectionControllerSectionDelegateTests: BaseSectionDelegateTests { + @MainActor override func createSectionDelegate() throws -> SectionDelegate { BaseSectionController() } diff --git a/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionDelegateTests.swift index db4a12c6..8a8f06e8 100644 --- a/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDelegate/BaseSectionDelegateTests.swift @@ -1,24 +1,25 @@ import SectionKit import XCTest -@MainActor -internal class BaseSectionDelegateTests: XCTestCase { +class BaseSectionDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseSectionDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createSectionDelegate() throws -> SectionDelegate { + @MainActor + func createSectionDelegate() throws -> SectionDelegate { throw XCTSkip("Tests from base class are skipped") } - internal func testShouldHighlightItem() throws { + @MainActor + func testShouldHighlightItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -29,7 +30,8 @@ internal class BaseSectionDelegateTests: XCTestCase { XCTAssert(sectionDelegate.shouldHighlightItem(at: indexPath, in: context)) } - internal func testDidHighlightItem() throws { + @MainActor + func testDidHighlightItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -40,7 +42,8 @@ internal class BaseSectionDelegateTests: XCTestCase { sectionDelegate.didHighlightItem(at: indexPath, in: context) } - internal func testDidUnhighlightItem() throws { + @MainActor + func testDidUnhighlightItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -51,7 +54,8 @@ internal class BaseSectionDelegateTests: XCTestCase { sectionDelegate.didUnhighlightItem(at: indexPath, in: context) } - internal func testShouldSelectItem() throws { + @MainActor + func testShouldSelectItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -62,7 +66,8 @@ internal class BaseSectionDelegateTests: XCTestCase { XCTAssert(sectionDelegate.shouldSelectItem(at: indexPath, in: context)) } - internal func testShouldDeselectItem() throws { + @MainActor + func testShouldDeselectItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -73,7 +78,8 @@ internal class BaseSectionDelegateTests: XCTestCase { XCTAssert(sectionDelegate.shouldDeselectItem(at: indexPath, in: context)) } - internal func testDidSelectItem() throws { + @MainActor + func testDidSelectItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -84,7 +90,8 @@ internal class BaseSectionDelegateTests: XCTestCase { sectionDelegate.didSelectItem(at: indexPath, in: context) } - internal func testDidDeselectItem() throws { + @MainActor + func testDidDeselectItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -95,7 +102,8 @@ internal class BaseSectionDelegateTests: XCTestCase { sectionDelegate.didDeselectItem(at: indexPath, in: context) } - internal func testWillDisplayCell() throws { + @MainActor + func testWillDisplayCell() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -110,7 +118,8 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } - internal func testWillDisplayHeaderView() throws { + @MainActor + func testWillDisplayHeaderView() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -125,7 +134,8 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } - internal func testWillDisplayFooterView() throws { + @MainActor + func testWillDisplayFooterView() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -140,7 +150,8 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } - internal func testDidEndDisplayingCell() throws { + @MainActor + func testDidEndDisplayingCell() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -155,7 +166,8 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } - internal func testDidEndDisplayingHeaderView() throws { + @MainActor + func testDidEndDisplayingHeaderView() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -170,7 +182,8 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } - internal func testDidEndDisplayingFooterView() throws { + @MainActor + func testDidEndDisplayingFooterView() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -186,8 +199,9 @@ internal class BaseSectionDelegateTests: XCTestCase { } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testShouldShowMenuForItem() throws { + func testShouldShowMenuForItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -202,8 +216,9 @@ internal class BaseSectionDelegateTests: XCTestCase { } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testCanPerform() throws { + func testCanPerform() throws { class Mock { @objc func perform() { } @@ -225,8 +240,9 @@ internal class BaseSectionDelegateTests: XCTestCase { } // availability attribute is needed because of deprecation warning + @MainActor @available(iOS, introduced: 6.0, deprecated: 13.0) - internal func testPerform() throws { + func testPerform() throws { class Mock { @objc func perform() { } @@ -247,7 +263,8 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } - internal func testCanFocusItem() throws { + @MainActor + func testCanFocusItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -267,8 +284,9 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } + @MainActor @available(iOS 11.0, *) - internal func testShouldSpringLoadItem() throws { + func testShouldSpringLoadItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -284,8 +302,9 @@ internal class BaseSectionDelegateTests: XCTestCase { )) } + @MainActor @available(iOS 13.0, *) - internal func testShouldBeginMultipleSelectionInteraction() throws { + func testShouldBeginMultipleSelectionInteraction() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -299,8 +318,9 @@ internal class BaseSectionDelegateTests: XCTestCase { )) } + @MainActor @available(iOS 13.0, *) - internal func testDidBeginMultipleSelectionInteraction() throws { + func testDidBeginMultipleSelectionInteraction() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -314,8 +334,9 @@ internal class BaseSectionDelegateTests: XCTestCase { ) } + @MainActor @available(iOS 13.0, *) - internal func testContextMenuConfigurationForItem() throws { + func testContextMenuConfigurationForItem() throws { let sectionDelegate = try createSectionDelegate() let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/SectionController/SectionDelegate/ProtocolDefaultValuesSectionDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDelegate/ProtocolDefaultValuesSectionDelegateTests.swift index cc57ad87..b908b3b1 100644 --- a/SectionKit/Tests/SectionController/SectionDelegate/ProtocolDefaultValuesSectionDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDelegate/ProtocolDefaultValuesSectionDelegateTests.swift @@ -1,8 +1,8 @@ import SectionKit import XCTest -@MainActor -internal final class ProtocolDefaultValuesSectionDelegateTests: BaseSectionDelegateTests { +final class ProtocolDefaultValuesSectionDelegateTests: BaseSectionDelegateTests { + @MainActor override func createSectionDelegate() throws -> SectionDelegate { class DefaultSectionDelegate: SectionDelegate { } return DefaultSectionDelegate() diff --git a/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionControllerSectionDragDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionControllerSectionDragDelegateTests.swift index 05b44795..6d8cb1dc 100644 --- a/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionControllerSectionDragDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionControllerSectionDragDelegateTests.swift @@ -1,9 +1,9 @@ import SectionKit import XCTest -@MainActor @available(iOS 11.0, *) -internal final class BaseSectionControllerSectionDragDelegateTests: BaseSectionDragDelegateTests { +final class BaseSectionControllerSectionDragDelegateTests: BaseSectionDragDelegateTests { + @MainActor override func createSectionDragDelegate() throws -> SectionDragDelegate { BaseSectionController() } diff --git a/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionDragDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionDragDelegateTests.swift index 0ca1b261..e0b7d7ab 100644 --- a/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionDragDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDragDelegate/BaseSectionDragDelegateTests.swift @@ -1,25 +1,26 @@ import SectionKit import XCTest -@MainActor @available(iOS 11.0, *) -internal class BaseSectionDragDelegateTests: XCTestCase { +class BaseSectionDragDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseSectionDragDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createSectionDragDelegate() throws -> SectionDragDelegate { + @MainActor + func createSectionDragDelegate() throws -> SectionDragDelegate { throw XCTSkip("Tests from base class are skipped") } - internal func testDragItemsForBeginning() throws { + @MainActor + func testDragItemsForBeginning() throws { let sectionDragDelegate = try createSectionDragDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -35,7 +36,8 @@ internal class BaseSectionDragDelegateTests: XCTestCase { ).isEmpty) } - internal func testDragItemsForAdding() throws { + @MainActor + func testDragItemsForAdding() throws { let sectionDragDelegate = try createSectionDragDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -52,7 +54,8 @@ internal class BaseSectionDragDelegateTests: XCTestCase { ).isEmpty) } - internal func testDragSessionWillBegin() throws { + @MainActor + func testDragSessionWillBegin() throws { let sectionDragDelegate = try createSectionDragDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -66,7 +69,8 @@ internal class BaseSectionDragDelegateTests: XCTestCase { ) } - internal func testDragSessionDidEnd() throws { + @MainActor + func testDragSessionDidEnd() throws { let sectionDragDelegate = try createSectionDragDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -80,7 +84,8 @@ internal class BaseSectionDragDelegateTests: XCTestCase { ) } - internal func testDragPreviewParametersForItem() throws { + @MainActor + func testDragPreviewParametersForItem() throws { let sectionDragDelegate = try createSectionDragDelegate() let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/SectionController/SectionDragDelegate/ProtocolDefaultValuesSectionDragDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDragDelegate/ProtocolDefaultValuesSectionDragDelegateTests.swift index c5b2a12e..8125a215 100644 --- a/SectionKit/Tests/SectionController/SectionDragDelegate/ProtocolDefaultValuesSectionDragDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDragDelegate/ProtocolDefaultValuesSectionDragDelegateTests.swift @@ -3,6 +3,7 @@ import XCTest @available(iOS 11.0, *) internal final class ProtocolDefaultValuesSectionDragDelegateTests: BaseSectionDragDelegateTests { + @MainActor override func createSectionDragDelegate() throws -> SectionDragDelegate { class DefaultSectionDragDelegate: SectionDragDelegate { func dragItems( diff --git a/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionControllerSectionDropDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionControllerSectionDropDelegateTests.swift index 7ca0e2a3..aebb9d34 100644 --- a/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionControllerSectionDropDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionControllerSectionDropDelegateTests.swift @@ -1,9 +1,9 @@ import SectionKit import XCTest -@MainActor @available(iOS 11.0, *) -internal final class BaseSectionControllerSectionDropDelegateTests: BaseSectionDropDelegateTests { +final class BaseSectionControllerSectionDropDelegateTests: BaseSectionDropDelegateTests { + @MainActor override func createSectionDropDelegate() throws -> SectionDropDelegate { BaseSectionController() } diff --git a/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionDropDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionDropDelegateTests.swift index c9977495..fe3b26d4 100644 --- a/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionDropDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDropDelegate/BaseSectionDropDelegateTests.swift @@ -1,25 +1,26 @@ import SectionKit import XCTest -@MainActor @available(iOS 11.0, *) -internal class BaseSectionDropDelegateTests: XCTestCase { +class BaseSectionDropDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseSectionDropDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createSectionDropDelegate() throws -> SectionDropDelegate { + @MainActor + func createSectionDropDelegate() throws -> SectionDropDelegate { throw XCTSkip("Tests from base class are skipped") } - internal func testCanHandle() throws { + @MainActor + func testCanHandle() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -33,7 +34,8 @@ internal class BaseSectionDropDelegateTests: XCTestCase { )) } - internal func testDropSessionDidUpdate() throws { + @MainActor + func testDropSessionDidUpdate() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -52,7 +54,8 @@ internal class BaseSectionDropDelegateTests: XCTestCase { ) } - internal func testPerformDrop() throws { + @MainActor + func testPerformDrop() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -68,7 +71,8 @@ internal class BaseSectionDropDelegateTests: XCTestCase { ) } - internal func testDropSessionDidEnter() throws { + @MainActor + func testDropSessionDidEnter() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -82,7 +86,8 @@ internal class BaseSectionDropDelegateTests: XCTestCase { ) } - internal func testDropSessionDidExit() throws { + @MainActor + func testDropSessionDidExit() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -96,7 +101,8 @@ internal class BaseSectionDropDelegateTests: XCTestCase { ) } - internal func testDropSessionDidEnd() throws { + @MainActor + func testDropSessionDidEnd() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -110,7 +116,8 @@ internal class BaseSectionDropDelegateTests: XCTestCase { ) } - internal func testDropPreviewParametersForItem() throws { + @MainActor + func testDropPreviewParametersForItem() throws { let sectionDropDelegate = try createSectionDropDelegate() let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/SectionController/SectionDropDelegate/ProtocolDefaultValuesSectionDropDelegateTests.swift b/SectionKit/Tests/SectionController/SectionDropDelegate/ProtocolDefaultValuesSectionDropDelegateTests.swift index 838d6eca..1d063d82 100644 --- a/SectionKit/Tests/SectionController/SectionDropDelegate/ProtocolDefaultValuesSectionDropDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionDropDelegate/ProtocolDefaultValuesSectionDropDelegateTests.swift @@ -1,9 +1,9 @@ import SectionKit import XCTest -@MainActor @available(iOS 11.0, *) internal final class ProtocolDefaultValuesSectionDropDelegateTests: BaseSectionDropDelegateTests { + @MainActor override func createSectionDropDelegate() throws -> SectionDropDelegate { class DefaultSectionDropDelegate: SectionDropDelegate { func performDrop( diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift index 4710fa1d..3aa2258a 100644 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift @@ -1,7 +1,7 @@ import SectionKit import XCTest -internal final class BaseFlowLayoutSectionControllerSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { +final class BaseFlowLayoutSectionControllerSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { @MainActor override func createSectionFlowDelegate() throws -> SectionFlowDelegate { BaseFlowLayoutSectionController() diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift index 526003c5..18d6a8ce 100644 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionFlowDelegateTests.swift @@ -1,25 +1,25 @@ import SectionKit import XCTest -internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { +class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseFlowLayoutSectionFlowDelegateTests.self else { return } throw XCTSkip("Tests from base class are skipped") } @MainActor - internal func createSectionFlowDelegate() throws -> SectionFlowDelegate { + func createSectionFlowDelegate() throws -> SectionFlowDelegate { throw XCTSkip("Tests from base class are skipped") } @MainActor - internal func testSizeForItemWithFlowLayout() throws { + func testSizeForItemWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -41,7 +41,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testSizeForItemWithoutFlowLayout() throws { + func testSizeForItemWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -61,7 +61,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testInsetWithFlowLayout() throws { + func testInsetWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -81,7 +81,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testInsetWithoutFlowLayout() throws { + func testInsetWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -99,7 +99,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testMinimumLineSpacingWithFlowLayout() throws { + func testMinimumLineSpacingWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -118,7 +118,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testMinimumLineSpacingWithoutFlowLayout() throws { + func testMinimumLineSpacingWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -136,7 +136,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testMinimumInteritemSpacingWithFlowLayout() throws { + func testMinimumInteritemSpacingWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -155,7 +155,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testMinimumInteritemSpacingWithoutFlowLayout() throws { + func testMinimumInteritemSpacingWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -173,7 +173,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testReferenceSizeForHeaderWithFlowLayout() throws { + func testReferenceSizeForHeaderWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -193,7 +193,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testReferenceSizeForHeaderWithoutFlowLayout() throws { + func testReferenceSizeForHeaderWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -211,7 +211,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testReferenceSizeForFooterWithFlowLayout() throws { + func testReferenceSizeForFooterWithFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, @@ -231,7 +231,7 @@ internal class BaseFlowLayoutSectionFlowDelegateTests: XCTestCase { } @MainActor - internal func testReferenceSizeForFooterWithoutFlowLayout() throws { + func testReferenceSizeForFooterWithoutFlowLayout() throws { let sectionFlowDelegate = try createSectionFlowDelegate() let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift index 8dd8e583..e464fc03 100644 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/ProtocolDefaultValuesSectionFlowDelegateTests.swift @@ -1,8 +1,8 @@ import SectionKit import XCTest -@MainActor -internal final class ProtocolDefaultValuesSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { +final class ProtocolDefaultValuesSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { + @MainActor override func createSectionFlowDelegate() throws -> SectionFlowDelegate { class DefaultSectionFlowDelegate: SectionFlowDelegate { } return DefaultSectionFlowDelegate() diff --git a/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift index 4077f3ee..fced1a85 100644 --- a/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift @@ -1,15 +1,16 @@ @testable import SectionKit import XCTest -@MainActor -internal final class SingleItemSectionControllerTests: XCTestCase { - internal func testDidUpdateModelWithValidTypeSetsModel() { +final class SingleItemSectionControllerTests: XCTestCase { + @MainActor + func testDidUpdateModelWithValidTypeSetsModel() { let sectionController = SingleItemSectionController(model: "1") sectionController.didUpdate(model: "2") XCTAssertEqual(sectionController.model, "2") } - internal func testDidUpdateModelWithInvalidType() { + @MainActor + func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionController = SingleItemSectionController(model: "1") let context = MainCollectionViewContext( @@ -32,7 +33,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testInitDoesNotUpdateItemIfShouldNotUpdateItem() { + @MainActor + func testInitDoesNotUpdateItemIfShouldNotUpdateItem() { class TestSectionController: SingleItemSectionController { var itemsForModelExpectation: XCTestExpectation? @@ -56,7 +58,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testSettingModelDoesNotUpdateItemIfShouldNotUpdateItem() { + @MainActor + func testSettingModelDoesNotUpdateItemIfShouldNotUpdateItem() { class TestSectionController: SingleItemSectionController { var itemsForModelExpectation: XCTestExpectation? @@ -83,12 +86,14 @@ internal final class SingleItemSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testShouldUpdateItemDefaultsToTrue() { + @MainActor + func testShouldUpdateItemDefaultsToTrue() { let sectionController = SingleItemSectionController(model: "1") XCTAssert(sectionController.shouldUpdateItem(afterModelChangedTo: "2")) } - internal func testItemForModelInvokesNotImplementedError() { + @MainActor + func testItemForModelInvokesNotImplementedError() { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionController = SingleItemSectionController(model: "1") let context = MainCollectionViewContext( @@ -108,7 +113,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testCalculateUpdateFromSomeToSomeWithEqualItems() throws { + @MainActor + func testCalculateUpdateFromSomeToSomeWithEqualItems() throws { let sectionController = SingleItemSectionController(model: "") let update = try XCTUnwrap( sectionController.calculateUpdate( @@ -125,7 +131,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromSomeToSomeWithDifferentItems() throws { + @MainActor + func testCalculateUpdateFromSomeToSomeWithDifferentItems() throws { let sectionController = SingleItemSectionController(model: "") let update = try XCTUnwrap( sectionController.calculateUpdate( @@ -142,7 +149,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromNoneToSome() throws { + @MainActor + func testCalculateUpdateFromNoneToSome() throws { let sectionController = SingleItemSectionController(model: "") let update = try XCTUnwrap( sectionController.calculateUpdate( @@ -159,7 +167,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromSomeToNone() throws { + @MainActor + func testCalculateUpdateFromSomeToNone() throws { let sectionController = SingleItemSectionController(model: "") let update = try XCTUnwrap( sectionController.calculateUpdate( @@ -176,7 +185,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testCalculateUpdateFromNoneToNone() throws { + @MainActor + func testCalculateUpdateFromNoneToNone() throws { let sectionController = SingleItemSectionController(model: "") let update = try XCTUnwrap( sectionController.calculateUpdate( @@ -193,7 +203,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { XCTAssertFalse(update.shouldReload(batchOperation)) } - internal func testNumberOfItemsWithItem() { + @MainActor + func testNumberOfItemsWithItem() { let sectionController = SingleItemSectionController(model: "1") sectionController.item = "1" let context = MainCollectionViewContext( @@ -204,7 +215,8 @@ internal final class SingleItemSectionControllerTests: XCTestCase { XCTAssertEqual(sectionController.numberOfItems(in: context), 1) } - internal func testNumberOfItemsWithoutItem() { + @MainActor + func testNumberOfItemsWithoutItem() { let sectionController = SingleItemSectionController(model: "1") sectionController.item = nil let context = MainCollectionViewContext( diff --git a/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift index 15c142e9..88b29c62 100644 --- a/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift @@ -1,15 +1,16 @@ @testable import SectionKit import XCTest -@MainActor -internal final class SingleModelSectionControllerTests: XCTestCase { - internal func testDidUpdateModelWithValidTypeSetsModel() { +final class SingleModelSectionControllerTests: XCTestCase { + @MainActor + func testDidUpdateModelWithValidTypeSetsModel() { let sectionController = SingleModelSectionController(model: "1") sectionController.didUpdate(model: "2") XCTAssertEqual(sectionController.model, "2") } - internal func testDidUpdateModelWithInvalidType() { + @MainActor + func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") let sectionController = SingleModelSectionController(model: "1") let context = MainCollectionViewContext( @@ -32,7 +33,8 @@ internal final class SingleModelSectionControllerTests: XCTestCase { waitForExpectations(timeout: 1) } - internal func testCalculateUpdateFromSomeToSomeWithDifferentItems() throws { + @MainActor + func testCalculateUpdateFromSomeToSomeWithDifferentItems() throws { let sectionController = SingleModelSectionController(model: 1) let update = try XCTUnwrap( sectionController.calculateUpdate( @@ -49,7 +51,8 @@ internal final class SingleModelSectionControllerTests: XCTestCase { XCTAssert(update.shouldReload(batchOperation)) } - internal func testNumberOfItems() { + @MainActor + func testNumberOfItems() { let sectionController = SingleModelSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, diff --git a/SectionKit/Tests/Utility/UICollectionViewApplyTests.swift b/SectionKit/Tests/Utility/UICollectionViewApplyTests.swift index e65b61dd..1e75842b 100644 --- a/SectionKit/Tests/Utility/UICollectionViewApplyTests.swift +++ b/SectionKit/Tests/Utility/UICollectionViewApplyTests.swift @@ -1,11 +1,11 @@ @testable import SectionKit import XCTest -@MainActor -internal final class UICollectionViewApplyTests: XCTestCase { +final class UICollectionViewApplyTests: XCTestCase { // MARK: - CollectionViewSectionUpdate - internal func testSectionUpdateEmptyBatchOperations() { + @MainActor + func testSectionUpdateEmptyBatchOperations() { let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let update = CollectionViewSectionUpdate( controller: BaseSectionController(), @@ -15,7 +15,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { collectionView.apply(update: update, at: 0) } - internal func testSectionUpdateWithoutWindowWithSingleBatchOperation() { + @MainActor + func testSectionUpdateWithoutWindowWithSingleBatchOperation() { let setDataExpectation = expectation(description: "Should invoke setData") let reloadDataExpectation = expectation(description: "Should invoke reloadData") let completionExpectation = expectation(description: "Should invoke completion of batch operation") @@ -51,7 +52,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { ) } - internal func testSectionUpdateWithoutWindowWithMultipleBatchOperations() { + @MainActor + func testSectionUpdateWithoutWindowWithMultipleBatchOperations() { let firstSetDataExpectation = expectation(description: "Should invoke setData for first data") let secondSetDataExpectation = expectation(description: "Should invoke setData for second data") let reloadDataExpectation = expectation(description: "Should invoke reloadData") @@ -106,7 +108,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { ) } - internal func testSectionUpdateWithWindowWithSingleBatchOperationWithAlwaysReload() { + @MainActor + func testSectionUpdateWithWindowWithSingleBatchOperationWithAlwaysReload() { let performBatchUpdatesExpectation = expectation(description: "Should invoke performBatchUpdates") let setDataExpectation = expectation(description: "Should invoke setData") let reloadSectionsExpectation = expectation(description: "Should invoke reloadSections") @@ -163,7 +166,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { ) } - internal func testSectionUpdateWithWindowWithSingleBatchOperationWithSeparateUpdates() { + @MainActor + func testSectionUpdateWithWindowWithSingleBatchOperationWithSeparateUpdates() { let performBatchUpdatesExpectation = expectation(description: "Should invoke performBatchUpdates") let setDataExpectation = expectation(description: "Should invoke setData") let deleteItemsExpectation = expectation(description: "Should invoke deleteItems") @@ -264,7 +268,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { // MARK: - CollectionViewUpdate - internal func testUpdateEmptyBatchOperations() { + @MainActor + func testUpdateEmptyBatchOperations() { let collectionView = MockCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()) let update = CollectionViewUpdate( batchOperations: [], @@ -308,7 +313,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { ) } - internal func testUpdateWithoutWindowWithMultipleBatchOperations() { + @MainActor + func testUpdateWithoutWindowWithMultipleBatchOperations() { let firstSetDataExpectation = expectation(description: "Should invoke setData for first data") let secondSetDataExpectation = expectation(description: "Should invoke setData for second data") let reloadDataExpectation = expectation(description: "Should invoke reloadData") @@ -361,7 +367,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { ) } - internal func testUpdateWithWindowWithSingleBatchOperationWithAlwaysReload() { + @MainActor + func testUpdateWithWindowWithSingleBatchOperationWithAlwaysReload() { let setDataExpectation = expectation(description: "Should invoke setData") let reloadDataExpectation = expectation(description: "Should invoke reloadData") let completionExpectation = expectation(description: "Should invoke completion of batch operation") @@ -408,7 +415,8 @@ internal final class UICollectionViewApplyTests: XCTestCase { ) } - internal func testUpdateWithWindowWithSingleBatchOperationWithSeparateUpdates() { + @MainActor + func testUpdateWithWindowWithSingleBatchOperationWithSeparateUpdates() { let performBatchUpdatesExpectation = expectation(description: "Should invoke performBatchUpdates") let setDataExpectation = expectation(description: "Should invoke setData") let deleteSectionsExpectation = expectation(description: "Should invoke deleteSections") From f43f715da9eae78b67a565bd19aaf94e6840fb0d Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 3 Apr 2024 15:27:41 +0200 Subject: [PATCH 07/24] Add the constants for the better reading --- .../BaseFlowLayoutSectionController.swift | 12 ++++----- .../SectionFlowDelegate.swift | 27 ++++++++++++++----- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift index c9b6ebe4..07ee64a4 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift @@ -14,35 +14,35 @@ open class BaseFlowLayoutSectionController: BaseSectionController, using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.itemSize ?? CGSize(width: 50, height: 50) + layout.flowLayout?.itemSize ?? FlowLayoutConstants.defaultItemSize } open func inset(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> UIEdgeInsets { - (layout as? UICollectionViewFlowLayout)?.sectionInset ?? .zero + layout.flowLayout?.sectionInset ?? FlowLayoutConstants.defaultInset } open func minimumLineSpacing(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> CGFloat { - (layout as? UICollectionViewFlowLayout)?.minimumLineSpacing ?? 10 + layout.flowLayout?.minimumLineSpacing ?? FlowLayoutConstants.defaultMinimumLineSpacing } open func minimumInteritemSpacing( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGFloat { - (layout as? UICollectionViewFlowLayout)?.minimumInteritemSpacing ?? 10 + layout.flowLayout?.minimumInteritemSpacing ?? FlowLayoutConstants.defaultMinimumInteritemSpacing } open func referenceSizeForHeader( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.headerReferenceSize ?? .zero + layout.flowLayout?.headerReferenceSize ?? FlowLayoutConstants.defaultHeaderSize } open func referenceSizeForFooter( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.footerReferenceSize ?? .zero + layout.flowLayout?.footerReferenceSize ?? FlowLayoutConstants.defaultFooterSize } } diff --git a/SectionKit/Sources/SectionController/SectionFlowDelegate.swift b/SectionKit/Sources/SectionController/SectionFlowDelegate.swift index 49cd338a..b3ae71a5 100644 --- a/SectionKit/Sources/SectionController/SectionFlowDelegate.swift +++ b/SectionKit/Sources/SectionController/SectionFlowDelegate.swift @@ -76,47 +76,62 @@ public protocol SectionFlowDelegate: AnyObject { func referenceSizeForFooter(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> CGSize } +enum FlowLayoutConstants { + static let defaultItemSize = CGSize(width: 50, height: 50) + static let defaultInset: UIEdgeInsets = .zero + static let defaultMinimumLineSpacing: CGFloat = 10 + static let defaultMinimumInteritemSpacing: CGFloat = 10 + static let defaultHeaderSize: CGSize = .zero + static let defaultFooterSize: CGSize = .zero +} + extension SectionFlowDelegate { public func sizeForItem( at indexPath: SectionIndexPath, using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.itemSize ?? CGSize(width: 50, height: 50) + layout.flowLayout?.itemSize ?? FlowLayoutConstants.defaultItemSize } public func inset( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> UIEdgeInsets { - (layout as? UICollectionViewFlowLayout)?.sectionInset ?? .zero + layout.flowLayout?.sectionInset ?? FlowLayoutConstants.defaultInset } public func minimumLineSpacing( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGFloat { - (layout as? UICollectionViewFlowLayout)?.minimumLineSpacing ?? 10 + layout.flowLayout?.minimumLineSpacing ?? FlowLayoutConstants.defaultMinimumLineSpacing } public func minimumInteritemSpacing( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGFloat { - (layout as? UICollectionViewFlowLayout)?.minimumInteritemSpacing ?? 10 + layout.flowLayout?.minimumInteritemSpacing ?? FlowLayoutConstants.defaultMinimumInteritemSpacing } public func referenceSizeForHeader( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.headerReferenceSize ?? .zero + layout.flowLayout?.headerReferenceSize ?? FlowLayoutConstants.defaultHeaderSize } public func referenceSizeForFooter( using layout: UICollectionViewLayout, in context: CollectionViewContext ) -> CGSize { - (layout as? UICollectionViewFlowLayout)?.footerReferenceSize ?? .zero + layout.flowLayout?.footerReferenceSize ?? FlowLayoutConstants.defaultFooterSize + } +} + +extension UICollectionViewLayout { + var flowLayout: UICollectionViewFlowLayout? { + self as? UICollectionViewFlowLayout } } From c796b81e6834a088532f6f07a27bb8950af7b5a0 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 10:31:08 +0200 Subject: [PATCH 08/24] add typealias --- ...fingListFlowLayoutSectionController.swift} | 11 ++++++++++- ...fingListFlowLayoutSectionController.swift} | 19 ++++++++++++++----- ...t => ListFlowLaoutSectionController.swift} | 10 +++++++++- ...ngleItemFlowLayoutSectionController.swift} | 12 ++++++++++-- ...gleModelFlowLayoutSectionController.swift} | 10 +++++++++- 5 files changed, 52 insertions(+), 10 deletions(-) rename DiffingSectionKit/Sources/{DiffingListSectionController.swift => DiffingListFlowLayoutSectionController.swift} (68%) rename DiffingSectionKit/Sources/{ManualDiffingListSectionController.swift => ManualDiffingListFlowLayoutSectionController.swift} (86%) rename SectionKit/Sources/SectionController/FlowLayout/{ListSectionController.swift => ListFlowLaoutSectionController.swift} (91%) rename SectionKit/Sources/SectionController/FlowLayout/{SingleItemSectionController.swift => SingleItemFlowLayoutSectionController.swift} (91%) rename SectionKit/Sources/SectionController/FlowLayout/{SingleModelSectionController.swift => SingleModelFlowLayoutSectionController.swift} (87%) diff --git a/DiffingSectionKit/Sources/DiffingListSectionController.swift b/DiffingSectionKit/Sources/DiffingListFlowLayoutSectionController.swift similarity index 68% rename from DiffingSectionKit/Sources/DiffingListSectionController.swift rename to DiffingSectionKit/Sources/DiffingListFlowLayoutSectionController.swift index 4d5cd989..714b2a2b 100644 --- a/DiffingSectionKit/Sources/DiffingListSectionController.swift +++ b/DiffingSectionKit/Sources/DiffingListFlowLayoutSectionController.swift @@ -9,7 +9,7 @@ import SectionKit of a model to be displayed and the list of items may dynamically change. */ @MainActor -open class DiffingListSectionController: ListSectionController { +open class DiffingListFlowLayoutSectionController: ListFlowLaoutSectionController { override open func calculateUpdate( from oldData: [Item], to newData: [Item] @@ -23,3 +23,12 @@ open class DiffingListSectionController: ListSectio ) } } + +@available( + *, + deprecated, + renamed: "DiffingListFlowLayoutSectionController", + message: "It has been renamed to DiffingListFlowLayoutSectionController" +) + +public typealias DiffingListSectionController = DiffingListFlowLayoutSectionController diff --git a/DiffingSectionKit/Sources/ManualDiffingListSectionController.swift b/DiffingSectionKit/Sources/ManualDiffingListFlowLayoutSectionController.swift similarity index 86% rename from DiffingSectionKit/Sources/ManualDiffingListSectionController.swift rename to DiffingSectionKit/Sources/ManualDiffingListFlowLayoutSectionController.swift index 53d42dba..93542e6f 100644 --- a/DiffingSectionKit/Sources/ManualDiffingListSectionController.swift +++ b/DiffingSectionKit/Sources/ManualDiffingListFlowLayoutSectionController.swift @@ -12,10 +12,10 @@ import SectionKit `Item` type, instead it requires closures to get diffing information for an item. */ @MainActor -open class ManualDiffingListSectionController< +open class ManualDiffingListFlowLayoutSectionController< Model, Item ->: ListSectionController { +>: ListFlowLaoutSectionController { private let itemId: @MainActor (Item) -> AnyHashable private let itemContentIsEqual: @MainActor (Item, Item) -> Bool @@ -55,7 +55,7 @@ open class ManualDiffingListSectionController< } } -extension ManualDiffingListSectionController where Item: Equatable { +extension ManualDiffingListFlowLayoutSectionController where Item: Equatable { /** Initialise an instance of `ManualDiffingListSectionController`. @@ -69,7 +69,7 @@ extension ManualDiffingListSectionController where Item: Equatable { } @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -extension ManualDiffingListSectionController where Item: Identifiable { +extension ManualDiffingListFlowLayoutSectionController where Item: Identifiable { /** Initialise an instance of `ManualDiffingListSectionController`. @@ -89,7 +89,7 @@ extension ManualDiffingListSectionController where Item: Identifiable { the base init (apart from the default values), we have to specify `@_disfavoredOverload` so it doesn't call itself. */ @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -extension ManualDiffingListSectionController where Item: Identifiable & Equatable { +extension ManualDiffingListFlowLayoutSectionController where Item: Identifiable & Equatable { /** Initialise an instance of `ManualDiffingListSectionController`. @@ -108,3 +108,12 @@ extension ManualDiffingListSectionController where Item: Identifiable & Equatabl self.init(model: model, itemId: itemId, itemContentIsEqual: itemContentIsEqual) } } + +@available( + *, + deprecated, + renamed: "ManualDiffingListFlowLayoutSectionController", + message: "It has been renamed to ManualDiffingListFlowLayoutSectionController" +) + +public typealias ManualDiffingListSectionController = ManualDiffingListFlowLayoutSectionController diff --git a/SectionKit/Sources/SectionController/FlowLayout/ListSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift similarity index 91% rename from SectionKit/Sources/SectionController/FlowLayout/ListSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift index d8d5124c..a3f016d4 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/ListSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift @@ -8,7 +8,7 @@ import UIKit of a model to be displayed and the list of items (almost) never changes or should not perform animated updates. */ @MainActor -open class ListSectionController: BaseFlowLayoutSectionController { +open class ListFlowLaoutSectionController: BaseFlowLayoutSectionController { /** Initialise an instance of `ListSectionController`. @@ -112,3 +112,11 @@ open class ListSectionController: BaseFlowLayoutSectionController { override open func numberOfItems(in context: CollectionViewContext) -> Int { items.count } } + +@available( + *, + deprecated, + renamed: "ListFlowLaoutSectionController", + message: "It has been renamed to ListFlowLaoutSectionController" +) +public typealias ListSectionController = ListFlowLaoutSectionController diff --git a/SectionKit/Sources/SectionController/FlowLayout/SingleItemSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/SingleItemFlowLayoutSectionController.swift similarity index 91% rename from SectionKit/Sources/SectionController/FlowLayout/SingleItemSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/SingleItemFlowLayoutSectionController.swift index 9f88725d..7ecb9e77 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/SingleItemSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/SingleItemFlowLayoutSectionController.swift @@ -9,7 +9,7 @@ import UIKit - Warning: If `numberOfItems` is overridden, `calculateUpdate(from:to:)` needs to be overridden as well. */ @MainActor -open class SingleItemSectionController: BaseFlowLayoutSectionController { +open class SingleItemFlowLayoutSectionController: BaseFlowLayoutSectionController { private let areItemsEqual: @MainActor (Item, Item) -> Bool /** @@ -133,7 +133,7 @@ open class SingleItemSectionController: BaseFlowLayoutSectionContro override open func numberOfItems(in context: CollectionViewContext) -> Int { item != nil ? 1 : 0 } } -extension SingleItemSectionController where Item: Equatable { +extension SingleItemFlowLayoutSectionController where Item: Equatable { /** Initialise an instance of `SingleItemSectionController` which will only reload when the new item is different from the old one. @@ -144,3 +144,11 @@ extension SingleItemSectionController where Item: Equatable { self.init(model: model, areItemsEqual: ==) } } + +@available( + *, + deprecated, + renamed: "SingleItemFlowLayoutSectionController", + message: "It has been renamed to SingleItemFlowLayoutSectionController" +) +public typealias SingleItemSectionController = SingleItemFlowLayoutSectionController diff --git a/SectionKit/Sources/SectionController/FlowLayout/SingleModelSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/SingleModelFlowLayoutSectionController.swift similarity index 87% rename from SectionKit/Sources/SectionController/FlowLayout/SingleModelSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/SingleModelFlowLayoutSectionController.swift index f2144b49..4a563ab6 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/SingleModelSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/SingleModelFlowLayoutSectionController.swift @@ -9,7 +9,7 @@ import UIKit it is recommended to use `ListSectionController` instead. */ @MainActor -open class SingleModelSectionController: BaseFlowLayoutSectionController { +open class SingleModelFlowLayoutSectionController: BaseFlowLayoutSectionController { /** Initialise an instance of `SingleModelSectionController`. @@ -76,3 +76,11 @@ open class SingleModelSectionController: BaseFlowLayoutSectionController override open func numberOfItems(in context: CollectionViewContext) -> Int { 1 } } + +@available( + *, + deprecated, + renamed: "SingleModelFlowLayoutSectionController", + message: "It has been renamed to SingleModelFlowLayoutSectionController" +) +public typealias SingleModelSectionController = SingleModelFlowLayoutSectionController From dc80cf69e5ca2d0e3b783176024bccd0802fdcbd Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 11:38:29 +0200 Subject: [PATCH 09/24] fix tests --- SectionKit.xcodeproj/project.pbxproj | 56 +++++++++---------- ...fingListFlowLayoutSectionController.swift} | 13 ++++- ...istFlowLayoutSectionControllerTests.swift} | 4 +- ...temFlowLayoutSectionControllerTests.swift} | 4 +- ...delFlowLayoutSectionControllerTests.swift} | 2 +- 5 files changed, 44 insertions(+), 35 deletions(-) rename SectionKit/Sources/SectionController/FlowLayout/{FoundationDiffingListSectionController.swift => FoundationDiffingListFlowLayoutSectionController.swift} (69%) rename SectionKit/Tests/SectionController/{ListSectionControllerTests.swift => ListFlowLayoutSectionControllerTests.swift} (96%) rename SectionKit/Tests/SectionController/{SingleItemSectionControllerTests.swift => SingleItemFlowLayoutSectionControllerTests.swift} (97%) rename SectionKit/Tests/SectionController/{SingleModelSectionControllerTests.swift => SingleModelFlowLayoutSectionControllerTests.swift} (96%) diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index ff259593..ed6b3fa6 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -33,9 +33,9 @@ 5A0B777A26B1A81300B054D4 /* MainCollectionViewContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777926B1A81300B054D4 /* MainCollectionViewContextTests.swift */; }; 5A0B777C26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */; }; 5A0B777E26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */; }; - 5A0B778026B299FF00B054D4 /* ListSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777F26B299FF00B054D4 /* ListSectionControllerTests.swift */; }; - 5A0B778226B2A92C00B054D4 /* SingleItemSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */; }; - 5A0B778426B2AA2000B054D4 /* SingleModelSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778326B2AA2000B054D4 /* SingleModelSectionControllerTests.swift */; }; + 5A0B778026B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */; }; + 5A0B778226B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778126B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift */; }; + 5A0B778426B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */; }; 5A0B778626B2AB7800B054D4 /* BaseSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */; }; 5A0B778926B3EA4D00B054D4 /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778826B3EA4D00B054D4 /* ErrorTests.swift */; }; 5A31B8B726BAE8A900036A3F /* BaseSectionDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8B526BAE8A300036A3F /* BaseSectionDataSourceTests.swift */; }; @@ -97,10 +97,7 @@ 5AE175EC2667DA3F00D4DCE1 /* SectionIndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */; }; 5AE175ED2667DA3F00D4DCE1 /* SectionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B32667DA3E00D4DCE1 /* SectionDelegate.swift */; }; 5AE175EE2667DA3F00D4DCE1 /* BaseSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */; }; - 5AE175EF2667DA3F00D4DCE1 /* ListSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B62667DA3E00D4DCE1 /* ListSectionController.swift */; }; - 5AE175F02667DA3F00D4DCE1 /* SingleItemSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B72667DA3F00D4DCE1 /* SingleItemSectionController.swift */; }; - 5AE175F12667DA3F00D4DCE1 /* SingleModelSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B82667DA3F00D4DCE1 /* SingleModelSectionController.swift */; }; - 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift */; }; + 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift */; }; 5AE175F32667DA3F00D4DCE1 /* SectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175BA2667DA3F00D4DCE1 /* SectionController.swift */; }; 5AE175F42667DA3F00D4DCE1 /* SectionDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175BB2667DA3F00D4DCE1 /* SectionDragDelegate.swift */; }; 5AE175F52667DA3F00D4DCE1 /* CollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175BD2667DA3F00D4DCE1 /* CollectionViewAdapter.swift */; }; @@ -130,6 +127,9 @@ 5AE176112667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175DD2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift */; }; 5AE1761B2667DA7000D4DCE1 /* SectionIndexPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE176132667DA7000D4DCE1 /* SectionIndexPathTests.swift */; }; 5AE1761E2667DA7000D4DCE1 /* SequenceUniqueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE176182667DA7000D4DCE1 /* SequenceUniqueTests.swift */; }; + D90764C32BC692BB0083306E /* ListFlowLaoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C02BC692BB0083306E /* ListFlowLaoutSectionController.swift */; }; + D90764C42BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C12BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift */; }; + D90764C52BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C22BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift */; }; D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */; }; D91425692BBBF79E0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */; }; D914257F2BBBF8310005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */; }; @@ -182,9 +182,9 @@ 5A0B777926B1A81300B054D4 /* MainCollectionViewContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainCollectionViewContextTests.swift; sourceTree = ""; }; 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewSectionBatchOperationTests.swift; sourceTree = ""; }; 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewBatchOperationTests.swift; sourceTree = ""; }; - 5A0B777F26B299FF00B054D4 /* ListSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSectionControllerTests.swift; sourceTree = ""; }; - 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleItemSectionControllerTests.swift; sourceTree = ""; }; - 5A0B778326B2AA2000B054D4 /* SingleModelSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleModelSectionControllerTests.swift; sourceTree = ""; }; + 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; + 5A0B778126B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleItemFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; + 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleModelFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionControllerTests.swift; sourceTree = ""; }; 5A0B778826B3EA4D00B054D4 /* ErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorTests.swift; sourceTree = ""; }; 5A31B8B526BAE8A300036A3F /* BaseSectionDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionDataSourceTests.swift; sourceTree = ""; }; @@ -249,10 +249,7 @@ 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionIndexPath.swift; sourceTree = ""; }; 5AE175B32667DA3E00D4DCE1 /* SectionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionDelegate.swift; sourceTree = ""; }; 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseSectionController.swift; sourceTree = ""; }; - 5AE175B62667DA3E00D4DCE1 /* ListSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListSectionController.swift; sourceTree = ""; }; - 5AE175B72667DA3F00D4DCE1 /* SingleItemSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleItemSectionController.swift; sourceTree = ""; }; - 5AE175B82667DA3F00D4DCE1 /* SingleModelSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleModelSectionController.swift; sourceTree = ""; }; - 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationDiffingListSectionController.swift; sourceTree = ""; }; + 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationDiffingListFlowLayoutSectionController.swift; sourceTree = ""; }; 5AE175BA2667DA3F00D4DCE1 /* SectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionController.swift; sourceTree = ""; }; 5AE175BB2667DA3F00D4DCE1 /* SectionDragDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionDragDelegate.swift; sourceTree = ""; }; 5AE175BD2667DA3F00D4DCE1 /* CollectionViewAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewAdapter.swift; sourceTree = ""; }; @@ -286,6 +283,9 @@ 5AE175DD2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleSectionCollectionViewAdapter.swift; sourceTree = ""; }; 5AE176132667DA7000D4DCE1 /* SectionIndexPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionIndexPathTests.swift; sourceTree = ""; }; 5AE176182667DA7000D4DCE1 /* SequenceUniqueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceUniqueTests.swift; sourceTree = ""; }; + D90764C02BC692BB0083306E /* ListFlowLaoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListFlowLaoutSectionController.swift; sourceTree = ""; }; + D90764C12BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleModelFlowLayoutSectionController.swift; sourceTree = ""; }; + D90764C22BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleItemFlowLayoutSectionController.swift; sourceTree = ""; }; D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCompositionalLayoutSectionController.swift; sourceTree = ""; }; D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionKitCompositionalLayout.swift; sourceTree = ""; }; D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseCompositionalLayoutSectionControllerTests.swift; sourceTree = ""; }; @@ -668,9 +668,9 @@ 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */, 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */, 5A31B8E126BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift */, - 5A0B777F26B299FF00B054D4 /* ListSectionControllerTests.swift */, - 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */, - 5A0B778326B2AA2000B054D4 /* SingleModelSectionControllerTests.swift */, + 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */, + 5A0B778126B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift */, + 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */, ); path = SectionController; sourceTree = ""; @@ -717,10 +717,10 @@ isa = PBXGroup; children = ( D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */, - 5AE175B62667DA3E00D4DCE1 /* ListSectionController.swift */, - 5AE175B72667DA3F00D4DCE1 /* SingleItemSectionController.swift */, - 5AE175B82667DA3F00D4DCE1 /* SingleModelSectionController.swift */, - 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift */, + D90764C02BC692BB0083306E /* ListFlowLaoutSectionController.swift */, + D90764C22BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift */, + D90764C12BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift */, + 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift */, ); path = FlowLayout; sourceTree = ""; @@ -876,22 +876,24 @@ D9CCE9B52BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift in Sources */, 5AE175F52667DA3F00D4DCE1 /* CollectionViewAdapter.swift in Sources */, 5AE175F32667DA3F00D4DCE1 /* SectionController.swift in Sources */, - 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListSectionController.swift in Sources */, + 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift in Sources */, D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */, 5AB6644626A854A9004DC230 /* ErrorHandling.swift in Sources */, 5AE176052667DA3F00D4DCE1 /* FoundationDiffingListCollectionViewAdapter.swift in Sources */, 5AE175E92667DA3F00D4DCE1 /* CollectionViewSectionBatchOperation.swift in Sources */, + D90764C42BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift in Sources */, 5AE175E02667DA3F00D4DCE1 /* Move.swift in Sources */, 5AE175EB2667DA3F00D4DCE1 /* SectionDataSourcePrefetchingDelegate.swift in Sources */, 5AE175EC2667DA3F00D4DCE1 /* SectionIndexPath.swift in Sources */, 5AE1760F2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */, 5AE1760A2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, - 5AE175F12667DA3F00D4DCE1 /* SingleModelSectionController.swift in Sources */, 5AE175FB2667DA3F00D4DCE1 /* CollectionViewUpdate.swift in Sources */, + D90764C32BC692BB0083306E /* ListFlowLaoutSectionController.swift in Sources */, D941851A2BBC123C001B5086 /* ListCompositionalLayoutSectionController.swift in Sources */, 5AE175E42667DA3F00D4DCE1 /* Collection+Extensions.swift in Sources */, 5AE175E12667DA3F00D4DCE1 /* IndexPath+IsValid.swift in Sources */, 5AE175F82667DA3F00D4DCE1 /* MainCollectionViewContext.swift in Sources */, + D90764C52BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift in Sources */, D91425862BBBFB930005E8CD /* BaseFlowLayoutSectionController.swift in Sources */, D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */, 5AE176102667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+Convenience.swift in Sources */, @@ -902,8 +904,6 @@ 5AE175E82667DA3F00D4DCE1 /* CollectionViewContext+CollectionViewSectionUpdate.swift in Sources */, 5AE175EA2667DA3F00D4DCE1 /* CollectionViewSectionUpdate.swift in Sources */, 5AE175F92667DA3F00D4DCE1 /* CollectionViewBatchOperation.swift in Sources */, - 5AE175EF2667DA3F00D4DCE1 /* ListSectionController.swift in Sources */, - 5AE175F02667DA3F00D4DCE1 /* SingleItemSectionController.swift in Sources */, 5AE175FD2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDropDelegate.swift in Sources */, 5AE176092667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDelegate.swift in Sources */, D93269A32BBBFC2700B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */, @@ -946,7 +946,7 @@ 5AB6642926A587AE004DC230 /* CollectionViewContextSizeTests.swift in Sources */, 5A31B8CF26BAE93900036A3F /* BaseSectionDropDelegateTests.swift in Sources */, 5A31B8BF26BAE8EE00036A3F /* BaseSectionControllerSectionDataSourcePrefetchingDelegateTests.swift in Sources */, - 5A0B778426B2AA2000B054D4 /* SingleModelSectionControllerTests.swift in Sources */, + 5A0B778426B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift in Sources */, 5A0B775926B0069700B054D4 /* BaseCollectionViewAdapterUICollectionViewDropDelegateTests.swift in Sources */, 5A0B776E26B19E8C00B054D4 /* MockSingleSectionCollectionViewAdapterDataSource.swift in Sources */, 5A8D3E5927E8D16200073712 /* MockCollectionViewAdapter.swift in Sources */, @@ -955,7 +955,7 @@ 5A31B8BB26BAE8D400036A3F /* ProtocolDefaultValuesSectionDataSourceTests.swift in Sources */, 5A0B774E26AF0C2100B054D4 /* BaseCollectionViewAdapterUIScrollViewDelegateTests.swift in Sources */, 5AA9D96826AAC9AF00679D88 /* BaseCollectionViewAdapterUICollectionViewDelegateTests.swift in Sources */, - 5A0B778026B299FF00B054D4 /* ListSectionControllerTests.swift in Sources */, + 5A0B778026B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift in Sources */, 5A0B775B26B006AA00B054D4 /* ListCollectionViewAdapterUICollectionViewDropDelegateTests.swift in Sources */, 5A31B8BD26BAE8E300036A3F /* BaseSectionDataSourcePrefetchingDelegateTests.swift in Sources */, 5A31B8C126BAE8F800036A3F /* ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests.swift in Sources */, @@ -996,7 +996,7 @@ 5AB6644926A86F4D004DC230 /* MockSectionDataSource.swift in Sources */, 5A31B8D126BAE94500036A3F /* BaseSectionControllerSectionDropDelegateTests.swift in Sources */, 5A31B8C526BAE90B00036A3F /* BaseSectionControllerSectionDelegateTests.swift in Sources */, - 5A0B778226B2A92C00B054D4 /* SingleItemSectionControllerTests.swift in Sources */, + 5A0B778226B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift in Sources */, 5A8D3E5527E8D11600073712 /* MockCollectionViewContext.swift in Sources */, 5A8D3E5727E8D14700073712 /* MockCollectionView.swift in Sources */, 5A0B777E26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift in Sources */, diff --git a/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift similarity index 69% rename from SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListSectionController.swift rename to SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift index c6a06e07..37ff065c 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListSectionController.swift +++ b/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift @@ -8,10 +8,10 @@ import Foundation */ @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @MainActor -open class FoundationDiffingListSectionController< +open class FoundationDiffingListFlowLayoutSectionController< Model, Item: Hashable ->: ListSectionController { +>: ListFlowLaoutSectionController { override open func calculateUpdate( from oldData: [Item], to newData: [Item] @@ -32,3 +32,12 @@ open class FoundationDiffingListSectionController< ) } } + +@available( + *, + deprecated, + renamed: "FoundationDiffingListFlowLayoutSectionController", + message: "It has been renamed to FoundationDiffingListFlowLayoutSectionController" +) +@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) +public typealias FoundationDiffingListSectionController = FoundationDiffingListFlowLayoutSectionController diff --git a/SectionKit/Tests/SectionController/ListSectionControllerTests.swift b/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift similarity index 96% rename from SectionKit/Tests/SectionController/ListSectionControllerTests.swift rename to SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift index be716a84..e0020b75 100644 --- a/SectionKit/Tests/SectionController/ListSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift @@ -12,7 +12,7 @@ final class ListSectionControllerTests: XCTestCase { @MainActor func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = ListSectionController(model: "1") + let sectionController = ListFlowLaoutSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), @@ -95,7 +95,7 @@ final class ListSectionControllerTests: XCTestCase { @MainActor func testItemsForModelInvokesNotImplementedError() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = ListSectionController(model: "1") + let sectionController = ListFlowLaoutSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), diff --git a/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleItemFlowLayoutSectionControllerTests.swift similarity index 97% rename from SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift rename to SectionKit/Tests/SectionController/SingleItemFlowLayoutSectionControllerTests.swift index fced1a85..5437eb39 100644 --- a/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/SingleItemFlowLayoutSectionControllerTests.swift @@ -12,7 +12,7 @@ final class SingleItemSectionControllerTests: XCTestCase { @MainActor func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = SingleItemSectionController(model: "1") + let sectionController = SingleItemFlowLayoutSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), @@ -95,7 +95,7 @@ final class SingleItemSectionControllerTests: XCTestCase { @MainActor func testItemForModelInvokesNotImplementedError() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = SingleItemSectionController(model: "1") + let sectionController = SingleItemFlowLayoutSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), diff --git a/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift similarity index 96% rename from SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift rename to SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift index 88b29c62..f90545d6 100644 --- a/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift @@ -12,7 +12,7 @@ final class SingleModelSectionControllerTests: XCTestCase { @MainActor func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = SingleModelSectionController(model: "1") + let sectionController = SingleModelFlowLayoutSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), From f5492f35a895305173f0d43ace64dead6ce8048e Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 14:30:50 +0200 Subject: [PATCH 10/24] merge the section controller with section layout provider and deprecated the old functions --- SectionKit.xcodeproj/project.pbxproj | 84 +++--------- ...istCollectionViewAdapter+Convenience.swift | 12 +- ...ionCollectionViewAdapter+Convenience.swift | 12 +- ...CompositionalLayoutSectionController.swift | 14 -- .../BaseFlowLayoutSectionController.swift | 48 ------- .../ListFlowLaoutSectionController.swift | 122 ------------------ .../Generic/BaseSectionController.swift | 79 ++++++++++++ ...ndationDiffingListSectionController.swift} | 13 +- .../ListSectionController.swift} | 11 +- .../SingleItemSectionController.swift} | 12 +- .../SingleModelSectionController.swift} | 10 +- .../SectionController/SectionController.swift | 52 ++++++-- .../SectionKitCompositionalLayout.swift | 9 +- ...ollectionViewDelegateFlowLayoutTests.swift | 84 ++++++------ ...ListFlowLayoutSectionControllerTests.swift | 4 +- ...sitionalLayoutSectionControllerTests.swift | 24 ---- ...onControllerSectionFlowDelegateTests.swift | 2 +- ...=> SingleItemSectionControllerTests.swift} | 4 +- ...odelFlowLayoutSectionControllerTests.swift | 2 +- .../MockFlowLayoutSectionController.swift | 10 -- .../TestUtilities/MockSectionController.swift | 10 ++ 21 files changed, 233 insertions(+), 385 deletions(-) delete mode 100644 SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift delete mode 100644 SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift delete mode 100644 SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift rename SectionKit/Sources/SectionController/{FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift => Generic/FoundationDiffingListSectionController.swift} (69%) rename SectionKit/Sources/SectionController/{CompositionalLayout/ListCompositionalLayoutSectionController.swift => Generic/ListSectionController.swift} (96%) rename SectionKit/Sources/SectionController/{FlowLayout/SingleItemFlowLayoutSectionController.swift => Generic/SingleItemSectionController.swift} (91%) rename SectionKit/Sources/SectionController/{FlowLayout/SingleModelFlowLayoutSectionController.swift => Generic/SingleModelSectionController.swift} (87%) delete mode 100644 SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift rename SectionKit/Tests/SectionController/{SingleItemFlowLayoutSectionControllerTests.swift => SingleItemSectionControllerTests.swift} (97%) delete mode 100644 SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index ed6b3fa6..4f1fc83c 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -34,7 +34,7 @@ 5A0B777C26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */; }; 5A0B777E26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */; }; 5A0B778026B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */; }; - 5A0B778226B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778126B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift */; }; + 5A0B778226B2A92C00B054D4 /* SingleItemSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */; }; 5A0B778426B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */; }; 5A0B778626B2AB7800B054D4 /* BaseSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */; }; 5A0B778926B3EA4D00B054D4 /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778826B3EA4D00B054D4 /* ErrorTests.swift */; }; @@ -97,7 +97,6 @@ 5AE175EC2667DA3F00D4DCE1 /* SectionIndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */; }; 5AE175ED2667DA3F00D4DCE1 /* SectionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B32667DA3E00D4DCE1 /* SectionDelegate.swift */; }; 5AE175EE2667DA3F00D4DCE1 /* BaseSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */; }; - 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift */; }; 5AE175F32667DA3F00D4DCE1 /* SectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175BA2667DA3F00D4DCE1 /* SectionController.swift */; }; 5AE175F42667DA3F00D4DCE1 /* SectionDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175BB2667DA3F00D4DCE1 /* SectionDragDelegate.swift */; }; 5AE175F52667DA3F00D4DCE1 /* CollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175BD2667DA3F00D4DCE1 /* CollectionViewAdapter.swift */; }; @@ -127,21 +126,17 @@ 5AE176112667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175DD2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift */; }; 5AE1761B2667DA7000D4DCE1 /* SectionIndexPathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE176132667DA7000D4DCE1 /* SectionIndexPathTests.swift */; }; 5AE1761E2667DA7000D4DCE1 /* SequenceUniqueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE176182667DA7000D4DCE1 /* SequenceUniqueTests.swift */; }; - D90764C32BC692BB0083306E /* ListFlowLaoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C02BC692BB0083306E /* ListFlowLaoutSectionController.swift */; }; - D90764C42BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C12BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift */; }; - D90764C52BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C22BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift */; }; + D90764CA2BC6B9120083306E /* FoundationDiffingListSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C62BC6B9120083306E /* FoundationDiffingListSectionController.swift */; }; + D90764CB2BC6B9120083306E /* ListSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C72BC6B9120083306E /* ListSectionController.swift */; }; + D90764CC2BC6B9120083306E /* SingleModelSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C82BC6B9120083306E /* SingleModelSectionController.swift */; }; + D90764CD2BC6B9120083306E /* SingleItemSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C92BC6B9120083306E /* SingleItemSectionController.swift */; }; D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */; }; - D91425692BBBF79E0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */; }; D914257F2BBBF8310005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */; }; - D91425822BBBF8780005E8CD /* MockFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425802BBBF8670005E8CD /* MockFlowLayoutSectionController.swift */; }; D91425852BBBFB840005E8CD /* ListCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CE2667DA3F00D4DCE1 /* ListCollectionViewAdapter.swift */; }; - D91425862BBBFB930005E8CD /* BaseFlowLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */; }; D91425872BBBFBA40005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */; }; D93269A22BBBFC2400B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CA2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift */; }; D93269A32BBBFC2700B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C92667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift */; }; D93269A42BBBFC2B00B33C32 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift */; }; - D941851A2BBC123C001B5086 /* ListCompositionalLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */; }; - D9CCE9B52BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */; }; D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */; }; /* End PBXBuildFile section */ @@ -183,7 +178,7 @@ 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewSectionBatchOperationTests.swift; sourceTree = ""; }; 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewBatchOperationTests.swift; sourceTree = ""; }; 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; - 5A0B778126B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleItemFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; + 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleItemSectionControllerTests.swift; sourceTree = ""; }; 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleModelFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionControllerTests.swift; sourceTree = ""; }; 5A0B778826B3EA4D00B054D4 /* ErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorTests.swift; sourceTree = ""; }; @@ -249,7 +244,6 @@ 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionIndexPath.swift; sourceTree = ""; }; 5AE175B32667DA3E00D4DCE1 /* SectionDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionDelegate.swift; sourceTree = ""; }; 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseSectionController.swift; sourceTree = ""; }; - 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationDiffingListFlowLayoutSectionController.swift; sourceTree = ""; }; 5AE175BA2667DA3F00D4DCE1 /* SectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionController.swift; sourceTree = ""; }; 5AE175BB2667DA3F00D4DCE1 /* SectionDragDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionDragDelegate.swift; sourceTree = ""; }; 5AE175BD2667DA3F00D4DCE1 /* CollectionViewAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionViewAdapter.swift; sourceTree = ""; }; @@ -283,17 +277,13 @@ 5AE175DD2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleSectionCollectionViewAdapter.swift; sourceTree = ""; }; 5AE176132667DA7000D4DCE1 /* SectionIndexPathTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionIndexPathTests.swift; sourceTree = ""; }; 5AE176182667DA7000D4DCE1 /* SequenceUniqueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceUniqueTests.swift; sourceTree = ""; }; - D90764C02BC692BB0083306E /* ListFlowLaoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListFlowLaoutSectionController.swift; sourceTree = ""; }; - D90764C12BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleModelFlowLayoutSectionController.swift; sourceTree = ""; }; - D90764C22BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleItemFlowLayoutSectionController.swift; sourceTree = ""; }; - D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListCompositionalLayoutSectionController.swift; sourceTree = ""; }; + D90764C62BC6B9120083306E /* FoundationDiffingListSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FoundationDiffingListSectionController.swift; sourceTree = ""; }; + D90764C72BC6B9120083306E /* ListSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListSectionController.swift; sourceTree = ""; }; + D90764C82BC6B9120083306E /* SingleModelSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleModelSectionController.swift; sourceTree = ""; }; + D90764C92BC6B9120083306E /* SingleItemSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleItemSectionController.swift; sourceTree = ""; }; D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionKitCompositionalLayout.swift; sourceTree = ""; }; - D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseCompositionalLayoutSectionControllerTests.swift; sourceTree = ""; }; D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionFlowDelegateTests.swift; sourceTree = ""; }; D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift; sourceTree = ""; }; - D91425802BBBF8670005E8CD /* MockFlowLayoutSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockFlowLayoutSectionController.swift; sourceTree = ""; }; - D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCompositionalLayoutSectionController.swift; sourceTree = ""; }; - D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionController.swift; sourceTree = ""; }; D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSCollectionLayoutSection+Empty.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -482,7 +472,6 @@ 5AA9D95126AAA5E000679D88 /* MockCollectionViewCell.swift */, 5A8D3E5327E8D0E200073712 /* MockCollectionViewContext.swift */, 5AA9D95526AAA61700679D88 /* MockErrorHandler.swift */, - D91425802BBBF8670005E8CD /* MockFlowLayoutSectionController.swift */, 5A0B776F26B19EB300B054D4 /* MockListCollectionViewAdapterDataSource.swift */, 5A0B775326AFF4D500B054D4 /* MockScrollViewDelegate.swift */, 5AB6644A26A86F7A004DC230 /* MockSectionController.swift */, @@ -561,8 +550,6 @@ isa = PBXGroup; children = ( D9CCE9B62BADF2FD00EED204 /* Generic */, - D9CCE9B32BADED5B00EED204 /* CompositionalLayout */, - D9CCE9B22BADED3D00EED204 /* FlowLayout */, 5AE175AD2667DA3E00D4DCE1 /* Update */, 5AE175B22667DA3E00D4DCE1 /* SectionIndexPath.swift */, 5AE175BA2667DA3F00D4DCE1 /* SectionController.swift */, @@ -657,7 +644,6 @@ 5AE176122667DA7000D4DCE1 /* SectionController */ = { isa = PBXGroup; children = ( - D91425672BBBF77C0005E8CD /* SectionCompositionalLayout */, 5A31B8AF26BAE81000036A3F /* SectionDataSource */, 5A31B8B026BAE82200036A3F /* SectionDataSourcePrefetchingDelegate */, 5A31B8B126BAE82D00036A3F /* SectionDelegate */, @@ -669,7 +655,7 @@ 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */, 5A31B8E126BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift */, 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */, - 5A0B778126B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift */, + 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */, 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */, ); path = SectionController; @@ -705,39 +691,14 @@ path = CollectionViewAdapter; sourceTree = ""; }; - D91425672BBBF77C0005E8CD /* SectionCompositionalLayout */ = { - isa = PBXGroup; - children = ( - D91425662BBBF77C0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift */, - ); - path = SectionCompositionalLayout; - sourceTree = ""; - }; - D9CCE9B22BADED3D00EED204 /* FlowLayout */ = { - isa = PBXGroup; - children = ( - D9CCE9B72BADF31D00EED204 /* BaseFlowLayoutSectionController.swift */, - D90764C02BC692BB0083306E /* ListFlowLaoutSectionController.swift */, - D90764C22BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift */, - D90764C12BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift */, - 5AE175B92667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift */, - ); - path = FlowLayout; - sourceTree = ""; - }; - D9CCE9B32BADED5B00EED204 /* CompositionalLayout */ = { - isa = PBXGroup; - children = ( - D9CCE9B42BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift */, - D91425622BBBF7320005E8CD /* ListCompositionalLayoutSectionController.swift */, - ); - path = CompositionalLayout; - sourceTree = ""; - }; D9CCE9B62BADF2FD00EED204 /* Generic */ = { isa = PBXGroup; children = ( 5AE175B52667DA3E00D4DCE1 /* BaseSectionController.swift */, + D90764C72BC6B9120083306E /* ListSectionController.swift */, + D90764C92BC6B9120083306E /* SingleItemSectionController.swift */, + D90764C82BC6B9120083306E /* SingleModelSectionController.swift */, + D90764C62BC6B9120083306E /* FoundationDiffingListSectionController.swift */, ); path = Generic; sourceTree = ""; @@ -865,6 +826,7 @@ 5AE1760B2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDropDelegate.swift in Sources */, 5AE176072667DA3F00D4DCE1 /* Section.swift in Sources */, 5AE175DF2667DA3F00D4DCE1 /* CollectionDifference+Changes.swift in Sources */, + D90764CB2BC6B9120083306E /* ListSectionController.swift in Sources */, 5AE175E62667DA3F00D4DCE1 /* SectionDataSource.swift in Sources */, 5AE176002667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegateFlowLayout.swift in Sources */, 5AE1760D2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */, @@ -872,29 +834,24 @@ 5AE175F42667DA3F00D4DCE1 /* SectionDragDelegate.swift in Sources */, 5AE176062667DA3F00D4DCE1 /* ListCollectionViewAdapterDataSource.swift in Sources */, 5AE175F62667DA3F00D4DCE1 /* CollectionViewContext+Size.swift in Sources */, + D90764CA2BC6B9120083306E /* FoundationDiffingListSectionController.swift in Sources */, D93269A22BBBFC2400B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, - D9CCE9B52BADED9400EED204 /* BaseCompositionalLayoutSectionController.swift in Sources */, 5AE175F52667DA3F00D4DCE1 /* CollectionViewAdapter.swift in Sources */, 5AE175F32667DA3F00D4DCE1 /* SectionController.swift in Sources */, - 5AE175F22667DA3F00D4DCE1 /* FoundationDiffingListFlowLayoutSectionController.swift in Sources */, D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */, 5AB6644626A854A9004DC230 /* ErrorHandling.swift in Sources */, 5AE176052667DA3F00D4DCE1 /* FoundationDiffingListCollectionViewAdapter.swift in Sources */, 5AE175E92667DA3F00D4DCE1 /* CollectionViewSectionBatchOperation.swift in Sources */, - D90764C42BC692BB0083306E /* SingleModelFlowLayoutSectionController.swift in Sources */, 5AE175E02667DA3F00D4DCE1 /* Move.swift in Sources */, + D90764CC2BC6B9120083306E /* SingleModelSectionController.swift in Sources */, 5AE175EB2667DA3F00D4DCE1 /* SectionDataSourcePrefetchingDelegate.swift in Sources */, 5AE175EC2667DA3F00D4DCE1 /* SectionIndexPath.swift in Sources */, 5AE1760F2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */, 5AE1760A2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */, 5AE175FB2667DA3F00D4DCE1 /* CollectionViewUpdate.swift in Sources */, - D90764C32BC692BB0083306E /* ListFlowLaoutSectionController.swift in Sources */, - D941851A2BBC123C001B5086 /* ListCompositionalLayoutSectionController.swift in Sources */, 5AE175E42667DA3F00D4DCE1 /* Collection+Extensions.swift in Sources */, 5AE175E12667DA3F00D4DCE1 /* IndexPath+IsValid.swift in Sources */, 5AE175F82667DA3F00D4DCE1 /* MainCollectionViewContext.swift in Sources */, - D90764C52BC692BB0083306E /* SingleItemFlowLayoutSectionController.swift in Sources */, - D91425862BBBFB930005E8CD /* BaseFlowLayoutSectionController.swift in Sources */, D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */, 5AE176102667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter+Convenience.swift in Sources */, 5AE175DE2667DA3F00D4DCE1 /* Sequence+Unique.swift in Sources */, @@ -913,6 +870,7 @@ 5AE175E72667DA3F00D4DCE1 /* SectionFlowDelegate.swift in Sources */, 5AE175E32667DA3F00D4DCE1 /* UICollectionView+Apply.swift in Sources */, 5AE176012667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDelegate.swift in Sources */, + D90764CD2BC6B9120083306E /* SingleItemSectionController.swift in Sources */, 5AE1760E2667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapterDataSource.swift in Sources */, 5AE176112667DA3F00D4DCE1 /* SingleSectionCollectionViewAdapter.swift in Sources */, D93269A42BBBFC2B00B33C32 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */, @@ -969,7 +927,6 @@ 5A0B778926B3EA4D00B054D4 /* ErrorTests.swift in Sources */, 5A31B8E226BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift in Sources */, 5AA9D95426AAA5EA00679D88 /* MockCollectionReusableView.swift in Sources */, - D91425822BBBF8780005E8CD /* MockFlowLayoutSectionController.swift in Sources */, 5A0B777C26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift in Sources */, 5A0B774526AED0F600B054D4 /* BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift in Sources */, 5A31B8C326BAE90300036A3F /* BaseSectionDelegateTests.swift in Sources */, @@ -992,11 +949,10 @@ 5A31B8CD26BAE92D00036A3F /* ProtocolDefaultValuesSectionDragDelegateTests.swift in Sources */, 5A0B774726AEE24700B054D4 /* MockSectionFlowDelegate.swift in Sources */, 5AA9D95826AAA65900679D88 /* ListCollectionViewAdapterUICollectionViewDataSourceTests.swift in Sources */, - D91425692BBBF79E0005E8CD /* BaseCompositionalLayoutSectionControllerTests.swift in Sources */, 5AB6644926A86F4D004DC230 /* MockSectionDataSource.swift in Sources */, 5A31B8D126BAE94500036A3F /* BaseSectionControllerSectionDropDelegateTests.swift in Sources */, 5A31B8C526BAE90B00036A3F /* BaseSectionControllerSectionDelegateTests.swift in Sources */, - 5A0B778226B2A92C00B054D4 /* SingleItemFlowLayoutSectionControllerTests.swift in Sources */, + 5A0B778226B2A92C00B054D4 /* SingleItemSectionControllerTests.swift in Sources */, 5A8D3E5527E8D11600073712 /* MockCollectionViewContext.swift in Sources */, 5A8D3E5727E8D14700073712 /* MockCollectionView.swift in Sources */, 5A0B777E26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift in Sources */, diff --git a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift index 9b1f82ab..ca76b284 100644 --- a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift @@ -58,12 +58,20 @@ extension ListCollectionViewAdapter { extension ListCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { - (controller(at: indexPath) as? FlowLayoutSectionController)?.flowDelegate + if #available(iOS 13.0, *) { + controller(at: indexPath)?.layoutProvider?.flowLayoutProvider + } else { + controller(at: indexPath)?.flowDelegate + } } @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { - (controller(at: index) as? FlowLayoutSectionController)?.flowDelegate + if #available(iOS 13.0, *) { + controller(at: index)?.layoutProvider?.flowLayoutProvider + } else { + controller(at: index)?.flowDelegate + } } } diff --git a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift index 4fb424e7..5dbeb43e 100644 --- a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift @@ -58,12 +58,20 @@ extension SingleSectionCollectionViewAdapter { extension SingleSectionCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { - (controller(at: indexPath) as? FlowLayoutSectionController)?.flowDelegate + if #available(iOS 13.0, *) { + controller(at: indexPath)?.layoutProvider?.flowLayoutProvider + } else { + controller(at: indexPath)?.flowDelegate + } } @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { - (controller(at: index) as? FlowLayoutSectionController)?.flowDelegate + if #available(iOS 13.0, *) { + controller(at: index)?.layoutProvider?.flowLayoutProvider + } else { + controller(at: index)?.flowDelegate + } } } diff --git a/SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift b/SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift deleted file mode 100644 index 7c2b5162..00000000 --- a/SectionKit/Sources/SectionController/CompositionalLayout/BaseCompositionalLayoutSectionController.swift +++ /dev/null @@ -1,14 +0,0 @@ -import UIKit - -/// This is a foundational implementation of `CompositionalLayoutSectionController`, adding the compositional layout section delegate function while inheriting from the `BaseSectionController`. -@MainActor -@available(iOS 13.0, *) -open class BaseCompositionalLayoutSectionController: BaseSectionController, - CompositionalLayoutSectionController { - open func layoutSection( - layoutEnvironment: any NSCollectionLayoutEnvironment - ) -> NSCollectionLayoutSection { - context?.errorHandler.nonCritical(error: .notImplemented()) - return .empty - } -} diff --git a/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift deleted file mode 100644 index 07ee64a4..00000000 --- a/SectionKit/Sources/SectionController/FlowLayout/BaseFlowLayoutSectionController.swift +++ /dev/null @@ -1,48 +0,0 @@ -import UIKit - -/// This is a foundational implementation of `FlowLayoutSectionController`, implementing the flow layout delegate while inheriting from the `BaseSectionController`. -@MainActor -open class BaseFlowLayoutSectionController: BaseSectionController, - SectionFlowDelegate, - FlowLayoutSectionController { - open var flowDelegate: SectionFlowDelegate? { self } - - // MARK: - SectionFlowDelegate - - open func sizeForItem( - at indexPath: SectionIndexPath, - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGSize { - layout.flowLayout?.itemSize ?? FlowLayoutConstants.defaultItemSize - } - - open func inset(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> UIEdgeInsets { - layout.flowLayout?.sectionInset ?? FlowLayoutConstants.defaultInset - } - - open func minimumLineSpacing(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> CGFloat { - layout.flowLayout?.minimumLineSpacing ?? FlowLayoutConstants.defaultMinimumLineSpacing - } - - open func minimumInteritemSpacing( - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGFloat { - layout.flowLayout?.minimumInteritemSpacing ?? FlowLayoutConstants.defaultMinimumInteritemSpacing - } - - open func referenceSizeForHeader( - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGSize { - layout.flowLayout?.headerReferenceSize ?? FlowLayoutConstants.defaultHeaderSize - } - - open func referenceSizeForFooter( - using layout: UICollectionViewLayout, - in context: CollectionViewContext - ) -> CGSize { - layout.flowLayout?.footerReferenceSize ?? FlowLayoutConstants.defaultFooterSize - } -} diff --git a/SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift b/SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift deleted file mode 100644 index a3f016d4..00000000 --- a/SectionKit/Sources/SectionController/FlowLayout/ListFlowLaoutSectionController.swift +++ /dev/null @@ -1,122 +0,0 @@ -import UIKit - -/** - A `SectionController` that contains a list of items. Changes to that list will result in a call to - `reloadSections(_:)` on the underlying `UICollectionView`. - - This `SectionController` is typically used when there are multiple semantically similar items - of a model to be displayed and the list of items (almost) never changes or should not perform animated updates. - */ -@MainActor -open class ListFlowLaoutSectionController: BaseFlowLayoutSectionController { - /** - Initialise an instance of `ListSectionController`. - - - Parameter model: The model of this `SectionController`. - */ - public init(model: Model) { - self.model = model - super.init() - if shouldUpdateItems(afterModelChangedTo: model) { - items = items(for: model) - } - } - - override open func didUpdate(model: Any) { - guard let model = model as? Model else { - context?.errorHandler.nonCritical( - error: .sectionControllerModelTypeMismatch( - expected: Model.self, - actual: type(of: model) - ) - ) - return - } - self.model = model - } - - /// The model of this `SectionController`. - open var model: Model { - didSet { - if shouldUpdateItems(afterModelChangedTo: model) { - items = items(for: model) - } - } - } - - /** - Determines if the list of items should be updated after the model was updated to a new value. - - The default value is `true`. - - - Parameter model: The new value of the model. - - - Returns: If the list of items should be updated after the model was updated to a new value. - */ - open func shouldUpdateItems(afterModelChangedTo model: Model) -> Bool { true } - - /** - Derives a list of items from the given `Model`. - - Will be called automatically if `shouldUpdateItems(afterModelChangedTo:)` returned `true`. - - - Parameter model: The new value of the model. - - - Returns: The new items to be displayed in this section. - */ - open func items(for model: Model) -> [Item] { - context?.errorHandler.nonCritical(error: .notImplemented()) - return [] - } - - /** - The list of items currently displayed in the `UICollectionView`. - - Only set this property if `UICollectionView` insertions and deletions are handled, otherwise use `items` instead. - */ - open var collectionViewItems: [Item] = [] - - /// The items of this section. - open var items: [Item] { - get { collectionViewItems } - set { - guard let context = context else { - collectionViewItems = newValue - return - } - if let sectionUpdate = calculateUpdate(from: collectionViewItems, to: newValue) { - context.apply(update: sectionUpdate) - } - } - } - - /** - Calculate the `UICollectionView` events using the difference from the old to the new data. - - - Parameter oldData: The old data currently displayed in the section. - - - Parameter newData: The new data that should be displayed in the section. - - - Returns: The update that should be performed on the section. - */ - open func calculateUpdate( - from oldData: [Item], - to newData: [Item] - ) -> CollectionViewSectionUpdate<[Item]>? { - CollectionViewSectionUpdate( - controller: self, - data: newData, - setData: { self.collectionViewItems = $0 } - ) - } - - override open func numberOfItems(in context: CollectionViewContext) -> Int { items.count } -} - -@available( - *, - deprecated, - renamed: "ListFlowLaoutSectionController", - message: "It has been renamed to ListFlowLaoutSectionController" -) -public typealias ListSectionController = ListFlowLaoutSectionController diff --git a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift index bb1b7151..e39f9e5d 100644 --- a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift @@ -8,6 +8,7 @@ open class BaseSectionController: SectionController, SectionDataSource, SectionDataSourcePrefetchingDelegate, SectionDelegate, + SectionFlowDelegate, SectionDragDelegate, SectionDropDelegate { // MARK: - Init @@ -31,6 +32,9 @@ open class BaseSectionController: SectionController, @available(iOS 11.0, *) open var dropDelegate: SectionDropDelegate? { self } + @available(iOS 13.0, *) + open var layoutProvider: SectionLayoutProvider? { .flowLayout(self) } + open func didUpdate(model: Any) { } // MARK: - SectionDataSource @@ -221,6 +225,81 @@ open class BaseSectionController: SectionController, nil } + // MARK: - SectionFlowDelegate + + @available( + iOS, + introduced: 6.0, + deprecated: 13.0, + message: "Please use the layoutProvider with the flowLayout type" + ) + open func sizeForItem( + at indexPath: SectionIndexPath, + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGSize { + layout.flowLayout?.itemSize ?? FlowLayoutConstants.defaultItemSize + } + + @available( + iOS, + introduced: 6.0, + deprecated: 13.0, + message: "Please use the layoutProvider with the flowLayout type" + ) + open func inset(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> UIEdgeInsets { + layout.flowLayout?.sectionInset ?? FlowLayoutConstants.defaultInset + } + + @available( + iOS, + introduced: 6.0, + deprecated: 13.0, + message: "Please use the layoutProvider with the flowLayout type" + ) + open func minimumLineSpacing(using layout: UICollectionViewLayout, in context: CollectionViewContext) -> CGFloat { + layout.flowLayout?.minimumLineSpacing ?? FlowLayoutConstants.defaultMinimumLineSpacing + } + + @available( + iOS, + introduced: 6.0, + deprecated: 13.0, + message: "Please use the layoutProvider with the flowLayout type" + ) + open func minimumInteritemSpacing( + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGFloat { + layout.flowLayout?.minimumInteritemSpacing ?? FlowLayoutConstants.defaultMinimumInteritemSpacing + } + + @available( + iOS, + introduced: 6.0, + deprecated: 13.0, + message: "Please use the layoutProvider with the flowLayout type" + ) + open func referenceSizeForHeader( + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGSize { + layout.flowLayout?.headerReferenceSize ?? FlowLayoutConstants.defaultHeaderSize + } + + @available( + iOS, + introduced: 6.0, + deprecated: 13.0, + message: "Please use the layoutProvider with the flowLayout type" + ) + open func referenceSizeForFooter( + using layout: UICollectionViewLayout, + in context: CollectionViewContext + ) -> CGSize { + layout.flowLayout?.footerReferenceSize ?? FlowLayoutConstants.defaultFooterSize + } + // MARK: - SectionDropDelegate @available(iOS 11.0, *) diff --git a/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift b/SectionKit/Sources/SectionController/Generic/FoundationDiffingListSectionController.swift similarity index 69% rename from SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift rename to SectionKit/Sources/SectionController/Generic/FoundationDiffingListSectionController.swift index 37ff065c..c6a06e07 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/FoundationDiffingListFlowLayoutSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/FoundationDiffingListSectionController.swift @@ -8,10 +8,10 @@ import Foundation */ @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) @MainActor -open class FoundationDiffingListFlowLayoutSectionController< +open class FoundationDiffingListSectionController< Model, Item: Hashable ->: ListFlowLaoutSectionController { +>: ListSectionController { override open func calculateUpdate( from oldData: [Item], to newData: [Item] @@ -32,12 +32,3 @@ open class FoundationDiffingListFlowLayoutSectionController< ) } } - -@available( - *, - deprecated, - renamed: "FoundationDiffingListFlowLayoutSectionController", - message: "It has been renamed to FoundationDiffingListFlowLayoutSectionController" -) -@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -public typealias FoundationDiffingListSectionController = FoundationDiffingListFlowLayoutSectionController diff --git a/SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift b/SectionKit/Sources/SectionController/Generic/ListSectionController.swift similarity index 96% rename from SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift rename to SectionKit/Sources/SectionController/Generic/ListSectionController.swift index fcaf743a..cc216a4b 100644 --- a/SectionKit/Sources/SectionController/CompositionalLayout/ListCompositionalLayoutSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/ListSectionController.swift @@ -8,8 +8,7 @@ import UIKit of a model to be displayed and the list of items (almost) never changes or should not perform animated updates. */ @MainActor -@available(iOS 13.0, *) -open class ListCompositionalLayoutSectionController: BaseCompositionalLayoutSectionController { +open class ListSectionController: BaseSectionController { /** Initialise an instance of `ListSectionController`. @@ -72,7 +71,7 @@ open class ListCompositionalLayoutSectionController: BaseCompositio /** The list of items currently displayed in the `UICollectionView`. - + Only set this property if `UICollectionView` insertions and deletions are handled, otherwise use `items` instead. */ open var collectionViewItems: [Item] = [] @@ -93,11 +92,11 @@ open class ListCompositionalLayoutSectionController: BaseCompositio /** Calculate the `UICollectionView` events using the difference from the old to the new data. - + - Parameter oldData: The old data currently displayed in the section. - + - Parameter newData: The new data that should be displayed in the section. - + - Returns: The update that should be performed on the section. */ open func calculateUpdate( diff --git a/SectionKit/Sources/SectionController/FlowLayout/SingleItemFlowLayoutSectionController.swift b/SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift similarity index 91% rename from SectionKit/Sources/SectionController/FlowLayout/SingleItemFlowLayoutSectionController.swift rename to SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift index 7ecb9e77..e003fff9 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/SingleItemFlowLayoutSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/SingleItemSectionController.swift @@ -9,7 +9,7 @@ import UIKit - Warning: If `numberOfItems` is overridden, `calculateUpdate(from:to:)` needs to be overridden as well. */ @MainActor -open class SingleItemFlowLayoutSectionController: BaseFlowLayoutSectionController { +open class SingleItemSectionController: BaseSectionController { private let areItemsEqual: @MainActor (Item, Item) -> Bool /** @@ -133,7 +133,7 @@ open class SingleItemFlowLayoutSectionController: BaseFlowLayoutSec override open func numberOfItems(in context: CollectionViewContext) -> Int { item != nil ? 1 : 0 } } -extension SingleItemFlowLayoutSectionController where Item: Equatable { +extension SingleItemSectionController where Item: Equatable { /** Initialise an instance of `SingleItemSectionController` which will only reload when the new item is different from the old one. @@ -144,11 +144,3 @@ extension SingleItemFlowLayoutSectionController where Item: Equatable { self.init(model: model, areItemsEqual: ==) } } - -@available( - *, - deprecated, - renamed: "SingleItemFlowLayoutSectionController", - message: "It has been renamed to SingleItemFlowLayoutSectionController" -) -public typealias SingleItemSectionController = SingleItemFlowLayoutSectionController diff --git a/SectionKit/Sources/SectionController/FlowLayout/SingleModelFlowLayoutSectionController.swift b/SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift similarity index 87% rename from SectionKit/Sources/SectionController/FlowLayout/SingleModelFlowLayoutSectionController.swift rename to SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift index 4a563ab6..143408d1 100644 --- a/SectionKit/Sources/SectionController/FlowLayout/SingleModelFlowLayoutSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/SingleModelSectionController.swift @@ -9,7 +9,7 @@ import UIKit it is recommended to use `ListSectionController` instead. */ @MainActor -open class SingleModelFlowLayoutSectionController: BaseFlowLayoutSectionController { +open class SingleModelSectionController: BaseSectionController { /** Initialise an instance of `SingleModelSectionController`. @@ -76,11 +76,3 @@ open class SingleModelFlowLayoutSectionController: BaseFlowLayoutSectionC override open func numberOfItems(in context: CollectionViewContext) -> Int { 1 } } - -@available( - *, - deprecated, - renamed: "SingleModelFlowLayoutSectionController", - message: "It has been renamed to SingleModelFlowLayoutSectionController" -) -public typealias SingleModelSectionController = SingleModelFlowLayoutSectionController diff --git a/SectionKit/Sources/SectionController/SectionController.swift b/SectionKit/Sources/SectionController/SectionController.swift index 78e14e54..b49bb6fd 100644 --- a/SectionKit/Sources/SectionController/SectionController.swift +++ b/SectionKit/Sources/SectionController/SectionController.swift @@ -16,6 +16,9 @@ public protocol SectionController: AnyObject { /// The delegate of this section. var delegate: SectionDelegate? { get } + /// The delegate for the `UICollectionViewFlowLayout` of this section. + var flowDelegate: SectionFlowDelegate? { get } + /// The drag delegate of this section. @available(iOS 11.0, *) var dragDelegate: SectionDragDelegate? { get } @@ -24,6 +27,9 @@ public protocol SectionController: AnyObject { @available(iOS 11.0, *) var dropDelegate: SectionDropDelegate? { get } + @available(iOS 13.0, *) + var layoutProvider: SectionLayoutProvider? { get } + /// The model of this section controller changed. func didUpdate(model: Any) } @@ -34,27 +40,55 @@ extension SectionController { public var delegate: SectionDelegate? { nil } + public var flowDelegate: SectionFlowDelegate? { nil } + @available(iOS 11.0, *) public var dragDelegate: SectionDragDelegate? { nil } @available(iOS 11.0, *) public var dropDelegate: SectionDropDelegate? { nil } + + @available(iOS 13.0, *) + public var layoutProvider: SectionLayoutProvider? { nil } } -@MainActor -public protocol FlowLayoutSectionController: SectionController { - /// The delegate for the `UICollectionViewFlowLayout` of this section. - var flowDelegate: SectionFlowDelegate? { get } +@available(iOS 13.0, *) +public enum SectionLayoutProvider { + case flowLayout(FlowLayoutProvider) + case compositionalLayout(CompositionalLayoutProvider) } +public typealias FlowLayoutProvider = SectionFlowDelegate + @MainActor -public protocol CompositionalLayoutSectionController: SectionController { +@available(iOS 13.0, *) +public struct CompositionalLayoutProvider { /// Provide the layout section for the Compositional Layout /// - Parameters: /// - layoutEnvironment: the environment value for the layout /// - Returns: The layout for the section - @available(iOS 13.0, *) - func layoutSection( - layoutEnvironment: NSCollectionLayoutEnvironment - ) -> NSCollectionLayoutSection + var layoutSection: (_ layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection + + public init( + layoutSection: @escaping (any NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection + ) { + self.layoutSection = layoutSection + } +} + +@available(iOS 13.0, *) +public extension SectionLayoutProvider { + var flowLayoutProvider: FlowLayoutProvider? { + guard case .flowLayout(let flowLayoutProvider) = self else { + return nil + } + return flowLayoutProvider + } + + var compositionalLayoutProvider: CompositionalLayoutProvider? { + guard case .compositionalLayout(let compositionalLayoutProvider) = self else { + return nil + } + return compositionalLayoutProvider + } } diff --git a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift index b033cccf..8c119562 100644 --- a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift +++ b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift @@ -19,14 +19,11 @@ final public class SectionKitCompositionalLayout: UICollectionViewCompositionalL assertionFailure("Section index out of bound") return .empty } - guard let compositionalLayoutSectionController = sections[index].controller - as? BaseCompositionalLayoutSectionController else { - assertionFailure("Please use the `CompositionalLayoutSectionControler`") + guard case .compositionalLayout(let provider) = sections[index].controller.layoutProvider else { + assertionFailure("Please set the layout provider with `CompositionalLayoutProvider`") return .empty } - return compositionalLayoutSectionController.layoutSection( - layoutEnvironment: environment - ) + return provider.layoutSection(environment) } sections = { [weak self] in self?.sections?() ?? [] diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift index 121bd8c5..ace37e1c 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift @@ -44,8 +44,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = { + let sectionController = MockSectionController() + sectionController.layoutProvider = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._sizeForItem = { indexPath, layout, _ in XCTAssertEqual(indexPath.indexInCollectionView, itemIndexPath) @@ -53,7 +53,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: testExpectation.fulfill() return itemSize } - return flowDelegate + return .flowLayout(flowDelegate) }() return sectionController }) @@ -77,8 +77,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -98,8 +98,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -122,15 +122,15 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = { + let sectionController = MockSectionController() + sectionController.layoutProvider = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._inset = { layout, _ in XCTAssert(layout === mockLayout) testExpectation.fulfill() return sectionInset } - return flowDelegate + return .flowLayout(flowDelegate) }() return sectionController }) @@ -153,8 +153,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -173,8 +173,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -197,15 +197,15 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = { + let sectionController = MockSectionController() + sectionController.layoutProvider = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._minimumLineSpacing = { layout, _ in XCTAssert(layout === mockLayout) testExpectation.fulfill() return lineSpacing } - return flowDelegate + return .flowLayout(flowDelegate) }() return sectionController }) @@ -228,8 +228,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -248,8 +248,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -272,15 +272,15 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = { + let sectionController = MockSectionController() + sectionController.layoutProvider = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._minimumInteritemSpacing = { layout, _ in XCTAssert(layout === mockLayout) testExpectation.fulfill() return interitemSpacing } - return flowDelegate + return .flowLayout(flowDelegate) }() return sectionController }) @@ -303,8 +303,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -323,8 +323,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -347,15 +347,15 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = { + let sectionController = MockSectionController() + sectionController.layoutProvider = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._referenceSizeForHeader = { layout, _ in XCTAssert(layout === mockLayout) testExpectation.fulfill() return headerSize } - return flowDelegate + return .flowLayout(flowDelegate) }() return sectionController }) @@ -378,8 +378,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -398,8 +398,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -422,15 +422,15 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = { + let sectionController = MockSectionController() + sectionController.layoutProvider = { let flowDelegate = MockSectionFlowDelegate() flowDelegate._referenceSizeForFooter = { layout, _ in XCTAssert(layout === mockLayout) testExpectation.fulfill() return footerSize } - return flowDelegate + return .flowLayout(flowDelegate) }() return sectionController }) @@ -453,8 +453,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] @@ -473,8 +473,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: collectionView: collectionView, sections: [ Section(id: "", model: "", controller: { - let sectionController = MockFlowLayoutSectionController() - sectionController.flowDelegate = nil + let sectionController = MockSectionController() + sectionController.layoutProvider = nil return sectionController }) ] diff --git a/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift index e0020b75..be716a84 100644 --- a/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift @@ -12,7 +12,7 @@ final class ListSectionControllerTests: XCTestCase { @MainActor func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = ListFlowLaoutSectionController(model: "1") + let sectionController = ListSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), @@ -95,7 +95,7 @@ final class ListSectionControllerTests: XCTestCase { @MainActor func testItemsForModelInvokesNotImplementedError() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = ListFlowLaoutSectionController(model: "1") + let sectionController = ListSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), diff --git a/SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift deleted file mode 100644 index 528568ba..00000000 --- a/SectionKit/Tests/SectionController/SectionCompositionalLayout/BaseCompositionalLayoutSectionControllerTests.swift +++ /dev/null @@ -1,24 +0,0 @@ -@testable import SectionKit -import XCTest - -final class BaseCompositionalLayoutSectionControllerTests: XCTestCase { - final class TestLayoutEnvironment: NSObject, NSCollectionLayoutEnvironment { - final class TestLayoutContainer: NSObject, NSCollectionLayoutContainer { - let contentSize: CGSize = .zero - let effectiveContentSize: CGSize = .zero - let contentInsets: NSDirectionalEdgeInsets = .zero - let effectiveContentInsets: NSDirectionalEdgeInsets = .zero - } - let container: NSCollectionLayoutContainer = TestLayoutContainer() - let traitCollection: UITraitCollection = .current - } - - @MainActor - func test_layout_isEmpty() { - let sut = BaseCompositionalLayoutSectionController() - let layoutSection = sut.layoutSection( - layoutEnvironment: TestLayoutEnvironment() - ) - XCTAssertEqual(layoutSection, .empty) - } -} diff --git a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift index 3aa2258a..d26ce6e2 100644 --- a/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift +++ b/SectionKit/Tests/SectionController/SectionFlowDelegate/BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift @@ -4,6 +4,6 @@ import XCTest final class BaseFlowLayoutSectionControllerSectionFlowDelegateTests: BaseFlowLayoutSectionFlowDelegateTests { @MainActor override func createSectionFlowDelegate() throws -> SectionFlowDelegate { - BaseFlowLayoutSectionController() + BaseSectionController() } } diff --git a/SectionKit/Tests/SectionController/SingleItemFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift similarity index 97% rename from SectionKit/Tests/SectionController/SingleItemFlowLayoutSectionControllerTests.swift rename to SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift index 5437eb39..fced1a85 100644 --- a/SectionKit/Tests/SectionController/SingleItemFlowLayoutSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/SingleItemSectionControllerTests.swift @@ -12,7 +12,7 @@ final class SingleItemSectionControllerTests: XCTestCase { @MainActor func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = SingleItemFlowLayoutSectionController(model: "1") + let sectionController = SingleItemSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), @@ -95,7 +95,7 @@ final class SingleItemSectionControllerTests: XCTestCase { @MainActor func testItemForModelInvokesNotImplementedError() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = SingleItemFlowLayoutSectionController(model: "1") + let sectionController = SingleItemSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), diff --git a/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift index f90545d6..88b29c62 100644 --- a/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift @@ -12,7 +12,7 @@ final class SingleModelSectionControllerTests: XCTestCase { @MainActor func testDidUpdateModelWithInvalidType() { let errorExpectation = expectation(description: "The errorHandler should be called") - let sectionController = SingleModelFlowLayoutSectionController(model: "1") + let sectionController = SingleModelSectionController(model: "1") let context = MainCollectionViewContext( viewController: nil, collectionView: UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout()), diff --git a/SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift b/SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift deleted file mode 100644 index 7cf6be8f..00000000 --- a/SectionKit/Tests/TestUtilities/MockFlowLayoutSectionController.swift +++ /dev/null @@ -1,10 +0,0 @@ -import SectionKit -import XCTest - -final class MockFlowLayoutSectionController: MockSectionController, - FlowLayoutSectionController { - lazy var flowDelegate: SectionFlowDelegate? = { - XCTFail("flow delegate is not set") - return nil - }() -} diff --git a/SectionKit/Tests/TestUtilities/MockSectionController.swift b/SectionKit/Tests/TestUtilities/MockSectionController.swift index b6a8d80f..23ab185b 100644 --- a/SectionKit/Tests/TestUtilities/MockSectionController.swift +++ b/SectionKit/Tests/TestUtilities/MockSectionController.swift @@ -20,6 +20,11 @@ internal class MockSectionController: SectionController { return nil }() + internal lazy var flowDelegate: SectionFlowDelegate? = { + XCTFail("flow delegate is not set") + return nil + }() + @available(iOS 11.0, *) internal lazy var dragDelegate: SectionDragDelegate? = { XCTFail("dragDelegate is not set") @@ -37,6 +42,11 @@ internal class MockSectionController: SectionController { return MockErrorHandler() }() + internal lazy var layoutProvider: SectionLayoutProvider? = { + XCTFail("layoutProvider is not set") + return nil + }() + // MARK: - didUpdate internal typealias DidUpdateBlock = (Any) -> Void From 3728b830a5338406eecb7a0b4d7440df10470dd0 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 17:29:01 +0200 Subject: [PATCH 11/24] revert changes --- ...ift => DiffingListSectionController.swift} | 11 +-- ... ManualDiffingListSectionController.swift} | 19 ++--- .../Generic/BaseSectionController.swift | 85 ++++++++++--------- ...BaseFlowLayoutSectionControllerTests.swift | 10 --- .../BaseSectionControllerTests.swift | 5 ++ ...swift => ListSectionControllerTests.swift} | 0 6 files changed, 56 insertions(+), 74 deletions(-) rename DiffingSectionKit/Sources/{DiffingListFlowLayoutSectionController.swift => DiffingListSectionController.swift} (68%) rename DiffingSectionKit/Sources/{ManualDiffingListFlowLayoutSectionController.swift => ManualDiffingListSectionController.swift} (86%) delete mode 100644 SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift rename SectionKit/Tests/SectionController/{ListFlowLayoutSectionControllerTests.swift => ListSectionControllerTests.swift} (100%) diff --git a/DiffingSectionKit/Sources/DiffingListFlowLayoutSectionController.swift b/DiffingSectionKit/Sources/DiffingListSectionController.swift similarity index 68% rename from DiffingSectionKit/Sources/DiffingListFlowLayoutSectionController.swift rename to DiffingSectionKit/Sources/DiffingListSectionController.swift index 714b2a2b..4d5cd989 100644 --- a/DiffingSectionKit/Sources/DiffingListFlowLayoutSectionController.swift +++ b/DiffingSectionKit/Sources/DiffingListSectionController.swift @@ -9,7 +9,7 @@ import SectionKit of a model to be displayed and the list of items may dynamically change. */ @MainActor -open class DiffingListFlowLayoutSectionController: ListFlowLaoutSectionController { +open class DiffingListSectionController: ListSectionController { override open func calculateUpdate( from oldData: [Item], to newData: [Item] @@ -23,12 +23,3 @@ open class DiffingListFlowLayoutSectionController: ) } } - -@available( - *, - deprecated, - renamed: "DiffingListFlowLayoutSectionController", - message: "It has been renamed to DiffingListFlowLayoutSectionController" -) - -public typealias DiffingListSectionController = DiffingListFlowLayoutSectionController diff --git a/DiffingSectionKit/Sources/ManualDiffingListFlowLayoutSectionController.swift b/DiffingSectionKit/Sources/ManualDiffingListSectionController.swift similarity index 86% rename from DiffingSectionKit/Sources/ManualDiffingListFlowLayoutSectionController.swift rename to DiffingSectionKit/Sources/ManualDiffingListSectionController.swift index 93542e6f..53d42dba 100644 --- a/DiffingSectionKit/Sources/ManualDiffingListFlowLayoutSectionController.swift +++ b/DiffingSectionKit/Sources/ManualDiffingListSectionController.swift @@ -12,10 +12,10 @@ import SectionKit `Item` type, instead it requires closures to get diffing information for an item. */ @MainActor -open class ManualDiffingListFlowLayoutSectionController< +open class ManualDiffingListSectionController< Model, Item ->: ListFlowLaoutSectionController { +>: ListSectionController { private let itemId: @MainActor (Item) -> AnyHashable private let itemContentIsEqual: @MainActor (Item, Item) -> Bool @@ -55,7 +55,7 @@ open class ManualDiffingListFlowLayoutSectionController< } } -extension ManualDiffingListFlowLayoutSectionController where Item: Equatable { +extension ManualDiffingListSectionController where Item: Equatable { /** Initialise an instance of `ManualDiffingListSectionController`. @@ -69,7 +69,7 @@ extension ManualDiffingListFlowLayoutSectionController where Item: Equatable { } @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -extension ManualDiffingListFlowLayoutSectionController where Item: Identifiable { +extension ManualDiffingListSectionController where Item: Identifiable { /** Initialise an instance of `ManualDiffingListSectionController`. @@ -89,7 +89,7 @@ extension ManualDiffingListFlowLayoutSectionController where Item: Identifiable the base init (apart from the default values), we have to specify `@_disfavoredOverload` so it doesn't call itself. */ @available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *) -extension ManualDiffingListFlowLayoutSectionController where Item: Identifiable & Equatable { +extension ManualDiffingListSectionController where Item: Identifiable & Equatable { /** Initialise an instance of `ManualDiffingListSectionController`. @@ -108,12 +108,3 @@ extension ManualDiffingListFlowLayoutSectionController where Item: Identifiable self.init(model: model, itemId: itemId, itemContentIsEqual: itemContentIsEqual) } } - -@available( - *, - deprecated, - renamed: "ManualDiffingListFlowLayoutSectionController", - message: "It has been renamed to ManualDiffingListFlowLayoutSectionController" -) - -public typealias ManualDiffingListSectionController = ManualDiffingListFlowLayoutSectionController diff --git a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift index e39f9e5d..475d538f 100644 --- a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift @@ -1,8 +1,10 @@ import UIKit -/// This serves as a fundamental `SectionController` implementation, -/// encompassing data source and delegate protocols, with the exception of the flow layout delegate. -/// Each access control is designated as` open`, allowing for easy customization through overrides. +/** + A base implementation of all `SectionController` datasource and delegate protocols. + + Every declaration is marked `open` and can be overridden. + */ @MainActor open class BaseSectionController: SectionController, SectionDataSource, @@ -26,6 +28,8 @@ open class BaseSectionController: SectionController, open var delegate: SectionDelegate? { self } + open var flowDelegate: SectionFlowDelegate? { self } + @available(iOS 11.0, *) open var dragDelegate: SectionDragDelegate? { self } @@ -225,6 +229,44 @@ open class BaseSectionController: SectionController, nil } + // MARK: - SectionDropDelegate + + @available(iOS 11.0, *) + open func canHandle(drop session: UIDropSession, in context: CollectionViewContext) -> Bool { true } + + @available(iOS 11.0, *) + open func dropSessionDidUpdate( + _ session: UIDropSession, + at indexPath: SectionIndexPath?, + in context: CollectionViewContext + ) -> UICollectionViewDropProposal { + UICollectionViewDropProposal(operation: .forbidden) + } + + @available(iOS 11.0, *) + open func performDrop( + at indexPath: SectionIndexPath?, + with coordinator: UICollectionViewDropCoordinator, + in context: CollectionViewContext + ) { } + + @available(iOS 11.0, *) + open func dropSessionDidEnter(_ session: UIDropSession, in context: CollectionViewContext) { } + + @available(iOS 11.0, *) + open func dropSessionDidExit(_ session: UIDropSession, in context: CollectionViewContext) { } + + @available(iOS 11.0, *) + open func dropSessionDidEnd(_ session: UIDropSession, in context: CollectionViewContext) { } + + @available(iOS 11.0, *) + open func dropPreviewParametersForItem( + at indexPath: SectionIndexPath, + in context: CollectionViewContext + ) -> UIDragPreviewParameters? { + nil + } + // MARK: - SectionFlowDelegate @available( @@ -300,41 +342,4 @@ open class BaseSectionController: SectionController, layout.flowLayout?.footerReferenceSize ?? FlowLayoutConstants.defaultFooterSize } - // MARK: - SectionDropDelegate - - @available(iOS 11.0, *) - open func canHandle(drop session: UIDropSession, in context: CollectionViewContext) -> Bool { true } - - @available(iOS 11.0, *) - open func dropSessionDidUpdate( - _ session: UIDropSession, - at indexPath: SectionIndexPath?, - in context: CollectionViewContext - ) -> UICollectionViewDropProposal { - UICollectionViewDropProposal(operation: .forbidden) - } - - @available(iOS 11.0, *) - open func performDrop( - at indexPath: SectionIndexPath?, - with coordinator: UICollectionViewDropCoordinator, - in context: CollectionViewContext - ) { } - - @available(iOS 11.0, *) - open func dropSessionDidEnter(_ session: UIDropSession, in context: CollectionViewContext) { } - - @available(iOS 11.0, *) - open func dropSessionDidExit(_ session: UIDropSession, in context: CollectionViewContext) { } - - @available(iOS 11.0, *) - open func dropSessionDidEnd(_ session: UIDropSession, in context: CollectionViewContext) { } - - @available(iOS 11.0, *) - open func dropPreviewParametersForItem( - at indexPath: SectionIndexPath, - in context: CollectionViewContext - ) -> UIDragPreviewParameters? { - nil - } } diff --git a/SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift deleted file mode 100644 index e87dfe9d..00000000 --- a/SectionKit/Tests/SectionController/BaseFlowLayoutSectionControllerTests.swift +++ /dev/null @@ -1,10 +0,0 @@ -import SectionKit -import XCTest - -internal final class BaseFlowLayoutSectionControllerTests: XCTestCase { - @MainActor - internal func testFlowDelegateIsSelf() { - let sectionController = BaseFlowLayoutSectionController() - XCTAssert(sectionController.flowDelegate === sectionController) - } -} diff --git a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift index 0577bf6b..85b8522c 100644 --- a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift @@ -27,6 +27,11 @@ final class BaseSectionControllerTests: XCTestCase { XCTAssert(sectionController.delegate === sectionController) } + internal func testFlowDelegateIsSelf() { + let sectionController = BaseSectionController() + XCTAssert(sectionController.flowDelegate === sectionController) + } + @available(iOS 11.0, *) @MainActor func testDragDelegateIsSelf() { diff --git a/SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/ListSectionControllerTests.swift similarity index 100% rename from SectionKit/Tests/SectionController/ListFlowLayoutSectionControllerTests.swift rename to SectionKit/Tests/SectionController/ListSectionControllerTests.swift From 525d04bac1b8866b70aa380c507a8a41f742b61f Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 17:29:34 +0200 Subject: [PATCH 12/24] put return inside available to compatible with older versions --- .../ListCollectionViewAdapter+Convenience.swift | 8 ++++---- .../SingleSectionCollectionViewAdapter+Convenience.swift | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift index ca76b284..2ddbd2d7 100644 --- a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift @@ -59,18 +59,18 @@ extension ListCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - controller(at: indexPath)?.layoutProvider?.flowLayoutProvider + return controller(at: indexPath)?.layoutProvider?.flowLayoutProvider } else { - controller(at: indexPath)?.flowDelegate + return controller(at: indexPath)?.flowDelegate } } @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - controller(at: index)?.layoutProvider?.flowLayoutProvider + return controller(at: index)?.layoutProvider?.flowLayoutProvider } else { - controller(at: index)?.flowDelegate + return controller(at: index)?.flowDelegate } } } diff --git a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift index 5dbeb43e..d6666281 100644 --- a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift @@ -59,18 +59,18 @@ extension SingleSectionCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - controller(at: indexPath)?.layoutProvider?.flowLayoutProvider + return controller(at: indexPath)?.layoutProvider?.flowLayoutProvider } else { - controller(at: indexPath)?.flowDelegate + return controller(at: indexPath)?.flowDelegate } } @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - controller(at: index)?.layoutProvider?.flowLayoutProvider + return controller(at: index)?.layoutProvider?.flowLayoutProvider } else { - controller(at: index)?.flowDelegate + return controller(at: index)?.flowDelegate } } } From 3d3ba9aa382bbdcaea5ad319d9ee0d88c727d370 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 17:31:04 +0200 Subject: [PATCH 13/24] fix project file --- SectionKit.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index 4f1fc83c..2024c5b8 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -33,7 +33,6 @@ 5A0B777A26B1A81300B054D4 /* MainCollectionViewContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777926B1A81300B054D4 /* MainCollectionViewContextTests.swift */; }; 5A0B777C26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */; }; 5A0B777E26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */; }; - 5A0B778026B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */; }; 5A0B778226B2A92C00B054D4 /* SingleItemSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */; }; 5A0B778426B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */; }; 5A0B778626B2AB7800B054D4 /* BaseSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */; }; @@ -130,6 +129,7 @@ D90764CB2BC6B9120083306E /* ListSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C72BC6B9120083306E /* ListSectionController.swift */; }; D90764CC2BC6B9120083306E /* SingleModelSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C82BC6B9120083306E /* SingleModelSectionController.swift */; }; D90764CD2BC6B9120083306E /* SingleItemSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764C92BC6B9120083306E /* SingleItemSectionController.swift */; }; + D90764CF2BC6E8140083306E /* ListSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D90764CE2BC6E8140083306E /* ListSectionControllerTests.swift */; }; D91425652BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */; }; D914257F2BBBF8310005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */; }; D91425852BBBFB840005E8CD /* ListCollectionViewAdapter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CE2667DA3F00D4DCE1 /* ListCollectionViewAdapter.swift */; }; @@ -177,7 +177,6 @@ 5A0B777926B1A81300B054D4 /* MainCollectionViewContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainCollectionViewContextTests.swift; sourceTree = ""; }; 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewSectionBatchOperationTests.swift; sourceTree = ""; }; 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewBatchOperationTests.swift; sourceTree = ""; }; - 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleItemSectionControllerTests.swift; sourceTree = ""; }; 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleModelFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionControllerTests.swift; sourceTree = ""; }; @@ -281,6 +280,7 @@ D90764C72BC6B9120083306E /* ListSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListSectionController.swift; sourceTree = ""; }; D90764C82BC6B9120083306E /* SingleModelSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleModelSectionController.swift; sourceTree = ""; }; D90764C92BC6B9120083306E /* SingleItemSectionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleItemSectionController.swift; sourceTree = ""; }; + D90764CE2BC6E8140083306E /* ListSectionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListSectionControllerTests.swift; sourceTree = ""; }; D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionKitCompositionalLayout.swift; sourceTree = ""; }; D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionFlowDelegateTests.swift; sourceTree = ""; }; D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift; sourceTree = ""; }; @@ -654,7 +654,7 @@ 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */, 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */, 5A31B8E126BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift */, - 5A0B777F26B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift */, + D90764CE2BC6E8140083306E /* ListSectionControllerTests.swift */, 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */, 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */, ); @@ -894,6 +894,7 @@ 5A0B778626B2AB7800B054D4 /* BaseSectionControllerTests.swift in Sources */, 5A0B777026B19EB300B054D4 /* MockListCollectionViewAdapterDataSource.swift in Sources */, D914257F2BBBF8310005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift in Sources */, + D90764CF2BC6E8140083306E /* ListSectionControllerTests.swift in Sources */, 5A31B8E426BC36C400036A3F /* CollectionViewContextExtensionsTests.swift in Sources */, 5AA9D96E26AAD06100679D88 /* SingleSectionCollectionViewAdapterUICollectionViewDelegateTests.swift in Sources */, 5AE1761E2667DA7000D4DCE1 /* SequenceUniqueTests.swift in Sources */, @@ -913,7 +914,6 @@ 5A31B8BB26BAE8D400036A3F /* ProtocolDefaultValuesSectionDataSourceTests.swift in Sources */, 5A0B774E26AF0C2100B054D4 /* BaseCollectionViewAdapterUIScrollViewDelegateTests.swift in Sources */, 5AA9D96826AAC9AF00679D88 /* BaseCollectionViewAdapterUICollectionViewDelegateTests.swift in Sources */, - 5A0B778026B299FF00B054D4 /* ListFlowLayoutSectionControllerTests.swift in Sources */, 5A0B775B26B006AA00B054D4 /* ListCollectionViewAdapterUICollectionViewDropDelegateTests.swift in Sources */, 5A31B8BD26BAE8E300036A3F /* BaseSectionDataSourcePrefetchingDelegateTests.swift in Sources */, 5A31B8C126BAE8F800036A3F /* ProtocolDefaultValuesSectionDataSourcePrefetchingDelegateTests.swift in Sources */, From cf89c6f1bfde3abbb2fbb0be71d2b281e9c408fc Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 17:34:48 +0200 Subject: [PATCH 14/24] clean up --- ...trollerTests.swift => SingleModelSectionControllerTests.swift} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename SectionKit/Tests/SectionController/{SingleModelFlowLayoutSectionControllerTests.swift => SingleModelSectionControllerTests.swift} (100%) diff --git a/SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift b/SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift similarity index 100% rename from SectionKit/Tests/SectionController/SingleModelFlowLayoutSectionControllerTests.swift rename to SectionKit/Tests/SectionController/SingleModelSectionControllerTests.swift From 13105f49bdd22d5eedef29e3f3ae67e71a205595 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Tue, 2 Apr 2024 10:47:03 +0200 Subject: [PATCH 15/24] add new name example --- .../ExampleListCoordinator+Presentable.swift | 10 +- .../project.pbxproj | 14 +- .../Resources/first-names.json | 9893 +++++++++++++++++ .../VanillaSwiftExamples/Names/NameCell.swift | 29 + .../Names/NameSectionHeaderView.swift | 54 + ...esCoordinator+NamesSectionNavigation.swift | 13 + .../Names/NamesCoordinator+Presentable.swift | 14 + .../Names/NamesCoordinator.swift | 9 + .../Names/NamesSectionController.swift | 76 + .../Names/NamesSectionViewModel.swift | 46 + .../Names/NamesViewController.swift | 51 + .../Names/NamesViewModel.swift | 48 + 12 files changed, 10255 insertions(+), 2 deletions(-) create mode 100644 Example/SectionKitExample/Resources/first-names.json create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameCell.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameSectionHeaderView.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+NamesSectionNavigation.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+Presentable.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionViewModel.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewController.swift create mode 100644 Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewModel.swift diff --git a/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift b/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift index 64f3caf8..8702b4ab 100644 --- a/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift +++ b/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift @@ -36,7 +36,15 @@ extension ExampleListCoordinator: Presentable { navigationController: navigationController, presentable: VanillaSwiftExamples.EmojisCoordinator(navigationController: navigationController) ) - ) + ), + ExampleViewModel( + name: "Names", + description: "An MVVM-C arichitecture with compositional layout example by using a ListCompositionalLayoutCollectionViewAdapter that shows multiple ListCompositionalLayoutSectionController.", + navigation: ExampleCoordinator( + navigationController: navigationController, + presentable: NamesCoordinator(navigationController: navigationController) + ) + ), ] ), ExampleSectionViewModel( diff --git a/Example/SectionKitExample.xcodeproj/project.pbxproj b/Example/SectionKitExample.xcodeproj/project.pbxproj index bf65b45d..11986291 100644 --- a/Example/SectionKitExample.xcodeproj/project.pbxproj +++ b/Example/SectionKitExample.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -12,6 +12,7 @@ 5AFBBE14264BEF2B008C095D /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AFBBE13264BEF2B008C095D /* SceneDelegate.swift */; }; 5AFBBE18264BEF2C008C095D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5AFBBE17264BEF2C008C095D /* Assets.xcassets */; }; 5AFBBE1E264BEF2C008C095D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5AFBBE1C264BEF2C008C095D /* LaunchScreen.storyboard */; }; + D91425612BB478D90005E8CD /* first-names.json in Resources */ = {isa = PBXBuildFile; fileRef = D91425602BB478D90005E8CD /* first-names.json */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -27,6 +28,7 @@ 5AFBBE1F264BEF2C008C095D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5AFBBE25264BEF34008C095D /* tr-sectionkit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "tr-sectionkit"; path = ..; sourceTree = ""; }; 5AFBBE26264BEF41008C095D /* SectionKitExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SectionKitExample.entitlements; sourceTree = ""; }; + D91425602BB478D90005E8CD /* first-names.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "first-names.json"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -66,6 +68,7 @@ 5AFBBE10264BEF2B008C095D /* SectionKitExample */ = { isa = PBXGroup; children = ( + D914255F2BB478B60005E8CD /* Resources */, 5AFBBE11264BEF2B008C095D /* AppDelegate.swift */, 5AFBBE13264BEF2B008C095D /* SceneDelegate.swift */, 5AFBBE17264BEF2C008C095D /* Assets.xcassets */, @@ -83,6 +86,14 @@ name = Frameworks; sourceTree = ""; }; + D914255F2BB478B60005E8CD /* Resources */ = { + isa = PBXGroup; + children = ( + D91425602BB478D90005E8CD /* first-names.json */, + ); + path = Resources; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -146,6 +157,7 @@ buildActionMask = 2147483647; files = ( 5AFBBE1E264BEF2C008C095D /* LaunchScreen.storyboard in Resources */, + D91425612BB478D90005E8CD /* first-names.json in Resources */, 5AFBBE18264BEF2C008C095D /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Example/SectionKitExample/Resources/first-names.json b/Example/SectionKitExample/Resources/first-names.json new file mode 100644 index 00000000..580d1ac3 --- /dev/null +++ b/Example/SectionKitExample/Resources/first-names.json @@ -0,0 +1,9893 @@ +[ +"Aaren" +, +"Aarika" +, +"Abagael" +, +"Abagail" +, +"Abbe" +, +"Abbey" +, +"Abbi" +, +"Abbie" +, +"Abby" +, +"Abbye" +, +"Abigael" +, +"Abigail" +, +"Abigale" +, +"Abra" +, +"Ada" +, +"Adah" +, +"Adaline" +, +"Adan" +, +"Adara" +, +"Adda" +, +"Addi" +, +"Addia" +, +"Addie" +, +"Addy" +, +"Adel" +, +"Adela" +, +"Adelaida" +, +"Adelaide" +, +"Adele" +, +"Adelheid" +, +"Adelice" +, +"Adelina" +, +"Adelind" +, +"Adeline" +, +"Adella" +, +"Adelle" +, +"Adena" +, +"Adey" +, +"Adi" +, +"Adiana" +, +"Adina" +, +"Adora" +, +"Adore" +, +"Adoree" +, +"Adorne" +, +"Adrea" +, +"Adria" +, +"Adriaens" +, +"Adrian" +, +"Adriana" +, +"Adriane" +, +"Adrianna" +, +"Adrianne" +, +"Adriena" +, +"Adrienne" +, +"Aeriel" +, +"Aeriela" +, +"Aeriell" +, +"Afton" +, +"Ag" +, +"Agace" +, +"Agata" +, +"Agatha" +, +"Agathe" +, +"Aggi" +, +"Aggie" +, +"Aggy" +, +"Agna" +, +"Agnella" +, +"Agnes" +, +"Agnese" +, +"Agnesse" +, +"Agneta" +, +"Agnola" +, +"Agretha" +, +"Aida" +, +"Aidan" +, +"Aigneis" +, +"Aila" +, +"Aile" +, +"Ailee" +, +"Aileen" +, +"Ailene" +, +"Ailey" +, +"Aili" +, +"Ailina" +, +"Ailis" +, +"Ailsun" +, +"Ailyn" +, +"Aime" +, +"Aimee" +, +"Aimil" +, +"Aindrea" +, +"Ainslee" +, +"Ainsley" +, +"Ainslie" +, +"Ajay" +, +"Alaine" +, +"Alameda" +, +"Alana" +, +"Alanah" +, +"Alane" +, +"Alanna" +, +"Alayne" +, +"Alberta" +, +"Albertina" +, +"Albertine" +, +"Albina" +, +"Alecia" +, +"Aleda" +, +"Aleece" +, +"Aleen" +, +"Alejandra" +, +"Alejandrina" +, +"Alena" +, +"Alene" +, +"Alessandra" +, +"Aleta" +, +"Alethea" +, +"Alex" +, +"Alexa" +, +"Alexandra" +, +"Alexandrina" +, +"Alexi" +, +"Alexia" +, +"Alexina" +, +"Alexine" +, +"Alexis" +, +"Alfi" +, +"Alfie" +, +"Alfreda" +, +"Alfy" +, +"Ali" +, +"Alia" +, +"Alica" +, +"Alice" +, +"Alicea" +, +"Alicia" +, +"Alida" +, +"Alidia" +, +"Alie" +, +"Alika" +, +"Alikee" +, +"Alina" +, +"Aline" +, +"Alis" +, +"Alisa" +, +"Alisha" +, +"Alison" +, +"Alissa" +, +"Alisun" +, +"Alix" +, +"Aliza" +, +"Alla" +, +"Alleen" +, +"Allegra" +, +"Allene" +, +"Alli" +, +"Allianora" +, +"Allie" +, +"Allina" +, +"Allis" +, +"Allison" +, +"Allissa" +, +"Allix" +, +"Allsun" +, +"Allx" +, +"Ally" +, +"Allyce" +, +"Allyn" +, +"Allys" +, +"Allyson" +, +"Alma" +, +"Almeda" +, +"Almeria" +, +"Almeta" +, +"Almira" +, +"Almire" +, +"Aloise" +, +"Aloisia" +, +"Aloysia" +, +"Alta" +, +"Althea" +, +"Alvera" +, +"Alverta" +, +"Alvina" +, +"Alvinia" +, +"Alvira" +, +"Alyce" +, +"Alyda" +, +"Alys" +, +"Alysa" +, +"Alyse" +, +"Alysia" +, +"Alyson" +, +"Alyss" +, +"Alyssa" +, +"Amabel" +, +"Amabelle" +, +"Amalea" +, +"Amalee" +, +"Amaleta" +, +"Amalia" +, +"Amalie" +, +"Amalita" +, +"Amalle" +, +"Amanda" +, +"Amandi" +, +"Amandie" +, +"Amandy" +, +"Amara" +, +"Amargo" +, +"Amata" +, +"Amber" +, +"Amberly" +, +"Ambur" +, +"Ame" +, +"Amelia" +, +"Amelie" +, +"Amelina" +, +"Ameline" +, +"Amelita" +, +"Ami" +, +"Amie" +, +"Amii" +, +"Amil" +, +"Amitie" +, +"Amity" +, +"Ammamaria" +, +"Amy" +, +"Amye" +, +"Ana" +, +"Anabal" +, +"Anabel" +, +"Anabella" +, +"Anabelle" +, +"Analiese" +, +"Analise" +, +"Anallese" +, +"Anallise" +, +"Anastasia" +, +"Anastasie" +, +"Anastassia" +, +"Anatola" +, +"Andee" +, +"Andeee" +, +"Anderea" +, +"Andi" +, +"Andie" +, +"Andra" +, +"Andrea" +, +"Andreana" +, +"Andree" +, +"Andrei" +, +"Andria" +, +"Andriana" +, +"Andriette" +, +"Andromache" +, +"Andy" +, +"Anestassia" +, +"Anet" +, +"Anett" +, +"Anetta" +, +"Anette" +, +"Ange" +, +"Angel" +, +"Angela" +, +"Angele" +, +"Angelia" +, +"Angelica" +, +"Angelika" +, +"Angelina" +, +"Angeline" +, +"Angelique" +, +"Angelita" +, +"Angelle" +, +"Angie" +, +"Angil" +, +"Angy" +, +"Ania" +, +"Anica" +, +"Anissa" +, +"Anita" +, +"Anitra" +, +"Anjanette" +, +"Anjela" +, +"Ann" +, +"Ann-Marie" +, +"Anna" +, +"Anna-Diana" +, +"Anna-Diane" +, +"Anna-Maria" +, +"Annabal" +, +"Annabel" +, +"Annabela" +, +"Annabell" +, +"Annabella" +, +"Annabelle" +, +"Annadiana" +, +"Annadiane" +, +"Annalee" +, +"Annaliese" +, +"Annalise" +, +"Annamaria" +, +"Annamarie" +, +"Anne" +, +"Anne-Corinne" +, +"Anne-Marie" +, +"Annecorinne" +, +"Anneliese" +, +"Annelise" +, +"Annemarie" +, +"Annetta" +, +"Annette" +, +"Anni" +, +"Annice" +, +"Annie" +, +"Annis" +, +"Annissa" +, +"Annmaria" +, +"Annmarie" +, +"Annnora" +, +"Annora" +, +"Anny" +, +"Anselma" +, +"Ansley" +, +"Anstice" +, +"Anthe" +, +"Anthea" +, +"Anthia" +, +"Anthiathia" +, +"Antoinette" +, +"Antonella" +, +"Antonetta" +, +"Antonia" +, +"Antonie" +, +"Antonietta" +, +"Antonina" +, +"Anya" +, +"Appolonia" +, +"April" +, +"Aprilette" +, +"Ara" +, +"Arabel" +, +"Arabela" +, +"Arabele" +, +"Arabella" +, +"Arabelle" +, +"Arda" +, +"Ardath" +, +"Ardeen" +, +"Ardelia" +, +"Ardelis" +, +"Ardella" +, +"Ardelle" +, +"Arden" +, +"Ardene" +, +"Ardenia" +, +"Ardine" +, +"Ardis" +, +"Ardisj" +, +"Ardith" +, +"Ardra" +, +"Ardyce" +, +"Ardys" +, +"Ardyth" +, +"Aretha" +, +"Ariadne" +, +"Ariana" +, +"Aridatha" +, +"Ariel" +, +"Ariela" +, +"Ariella" +, +"Arielle" +, +"Arlana" +, +"Arlee" +, +"Arleen" +, +"Arlen" +, +"Arlena" +, +"Arlene" +, +"Arleta" +, +"Arlette" +, +"Arleyne" +, +"Arlie" +, +"Arliene" +, +"Arlina" +, +"Arlinda" +, +"Arline" +, +"Arluene" +, +"Arly" +, +"Arlyn" +, +"Arlyne" +, +"Aryn" +, +"Ashely" +, +"Ashia" +, +"Ashien" +, +"Ashil" +, +"Ashla" +, +"Ashlan" +, +"Ashlee" +, +"Ashleigh" +, +"Ashlen" +, +"Ashley" +, +"Ashli" +, +"Ashlie" +, +"Ashly" +, +"Asia" +, +"Astra" +, +"Astrid" +, +"Astrix" +, +"Atalanta" +, +"Athena" +, +"Athene" +, +"Atlanta" +, +"Atlante" +, +"Auberta" +, +"Aubine" +, +"Aubree" +, +"Aubrette" +, +"Aubrey" +, +"Aubrie" +, +"Aubry" +, +"Audi" +, +"Audie" +, +"Audra" +, +"Audre" +, +"Audrey" +, +"Audrie" +, +"Audry" +, +"Audrye" +, +"Audy" +, +"Augusta" +, +"Auguste" +, +"Augustina" +, +"Augustine" +, +"Aundrea" +, +"Aura" +, +"Aurea" +, +"Aurel" +, +"Aurelea" +, +"Aurelia" +, +"Aurelie" +, +"Auria" +, +"Aurie" +, +"Aurilia" +, +"Aurlie" +, +"Auroora" +, +"Aurora" +, +"Aurore" +, +"Austin" +, +"Austina" +, +"Austine" +, +"Ava" +, +"Aveline" +, +"Averil" +, +"Averyl" +, +"Avie" +, +"Avis" +, +"Aviva" +, +"Avivah" +, +"Avril" +, +"Avrit" +, +"Ayn" +, +"Bab" +, +"Babara" +, +"Babb" +, +"Babbette" +, +"Babbie" +, +"Babette" +, +"Babita" +, +"Babs" +, +"Bambi" +, +"Bambie" +, +"Bamby" +, +"Barb" +, +"Barbabra" +, +"Barbara" +, +"Barbara-Anne" +, +"Barbaraanne" +, +"Barbe" +, +"Barbee" +, +"Barbette" +, +"Barbey" +, +"Barbi" +, +"Barbie" +, +"Barbra" +, +"Barby" +, +"Bari" +, +"Barrie" +, +"Barry" +, +"Basia" +, +"Bathsheba" +, +"Batsheva" +, +"Bea" +, +"Beatrice" +, +"Beatrisa" +, +"Beatrix" +, +"Beatriz" +, +"Bebe" +, +"Becca" +, +"Becka" +, +"Becki" +, +"Beckie" +, +"Becky" +, +"Bee" +, +"Beilul" +, +"Beitris" +, +"Bekki" +, +"Bel" +, +"Belia" +, +"Belicia" +, +"Belinda" +, +"Belita" +, +"Bell" +, +"Bella" +, +"Bellanca" +, +"Belle" +, +"Bellina" +, +"Belva" +, +"Belvia" +, +"Bendite" +, +"Benedetta" +, +"Benedicta" +, +"Benedikta" +, +"Benetta" +, +"Benita" +, +"Benni" +, +"Bennie" +, +"Benny" +, +"Benoite" +, +"Berenice" +, +"Beret" +, +"Berget" +, +"Berna" +, +"Bernadene" +, +"Bernadette" +, +"Bernadina" +, +"Bernadine" +, +"Bernardina" +, +"Bernardine" +, +"Bernelle" +, +"Bernete" +, +"Bernetta" +, +"Bernette" +, +"Berni" +, +"Bernice" +, +"Bernie" +, +"Bernita" +, +"Berny" +, +"Berri" +, +"Berrie" +, +"Berry" +, +"Bert" +, +"Berta" +, +"Berte" +, +"Bertha" +, +"Berthe" +, +"Berti" +, +"Bertie" +, +"Bertina" +, +"Bertine" +, +"Berty" +, +"Beryl" +, +"Beryle" +, +"Bess" +, +"Bessie" +, +"Bessy" +, +"Beth" +, +"Bethanne" +, +"Bethany" +, +"Bethena" +, +"Bethina" +, +"Betsey" +, +"Betsy" +, +"Betta" +, +"Bette" +, +"Bette-Ann" +, +"Betteann" +, +"Betteanne" +, +"Betti" +, +"Bettina" +, +"Bettine" +, +"Betty" +, +"Bettye" +, +"Beulah" +, +"Bev" +, +"Beverie" +, +"Beverlee" +, +"Beverley" +, +"Beverlie" +, +"Beverly" +, +"Bevvy" +, +"Bianca" +, +"Bianka" +, +"Bibbie" +, +"Bibby" +, +"Bibbye" +, +"Bibi" +, +"Biddie" +, +"Biddy" +, +"Bidget" +, +"Bili" +, +"Bill" +, +"Billi" +, +"Billie" +, +"Billy" +, +"Billye" +, +"Binni" +, +"Binnie" +, +"Binny" +, +"Bird" +, +"Birdie" +, +"Birgit" +, +"Birgitta" +, +"Blair" +, +"Blaire" +, +"Blake" +, +"Blakelee" +, +"Blakeley" +, +"Blanca" +, +"Blanch" +, +"Blancha" +, +"Blanche" +, +"Blinni" +, +"Blinnie" +, +"Blinny" +, +"Bliss" +, +"Blisse" +, +"Blithe" +, +"Blondell" +, +"Blondelle" +, +"Blondie" +, +"Blondy" +, +"Blythe" +, +"Bobbe" +, +"Bobbee" +, +"Bobbette" +, +"Bobbi" +, +"Bobbie" +, +"Bobby" +, +"Bobbye" +, +"Bobette" +, +"Bobina" +, +"Bobine" +, +"Bobinette" +, +"Bonita" +, +"Bonnee" +, +"Bonni" +, +"Bonnibelle" +, +"Bonnie" +, +"Bonny" +, +"Brana" +, +"Brandais" +, +"Brande" +, +"Brandea" +, +"Brandi" +, +"Brandice" +, +"Brandie" +, +"Brandise" +, +"Brandy" +, +"Breanne" +, +"Brear" +, +"Bree" +, +"Breena" +, +"Bren" +, +"Brena" +, +"Brenda" +, +"Brenn" +, +"Brenna" +, +"Brett" +, +"Bria" +, +"Briana" +, +"Brianna" +, +"Brianne" +, +"Bride" +, +"Bridget" +, +"Bridgette" +, +"Bridie" +, +"Brier" +, +"Brietta" +, +"Brigid" +, +"Brigida" +, +"Brigit" +, +"Brigitta" +, +"Brigitte" +, +"Brina" +, +"Briney" +, +"Brinn" +, +"Brinna" +, +"Briny" +, +"Brit" +, +"Brita" +, +"Britney" +, +"Britni" +, +"Britt" +, +"Britta" +, +"Brittan" +, +"Brittaney" +, +"Brittani" +, +"Brittany" +, +"Britte" +, +"Britteny" +, +"Brittne" +, +"Brittney" +, +"Brittni" +, +"Brook" +, +"Brooke" +, +"Brooks" +, +"Brunhilda" +, +"Brunhilde" +, +"Bryana" +, +"Bryn" +, +"Bryna" +, +"Brynn" +, +"Brynna" +, +"Brynne" +, +"Buffy" +, +"Bunni" +, +"Bunnie" +, +"Bunny" +, +"Cacilia" +, +"Cacilie" +, +"Cahra" +, +"Cairistiona" +, +"Caitlin" +, +"Caitrin" +, +"Cal" +, +"Calida" +, +"Calla" +, +"Calley" +, +"Calli" +, +"Callida" +, +"Callie" +, +"Cally" +, +"Calypso" +, +"Cam" +, +"Camala" +, +"Camel" +, +"Camella" +, +"Camellia" +, +"Cami" +, +"Camila" +, +"Camile" +, +"Camilla" +, +"Camille" +, +"Cammi" +, +"Cammie" +, +"Cammy" +, +"Candace" +, +"Candi" +, +"Candice" +, +"Candida" +, +"Candide" +, +"Candie" +, +"Candis" +, +"Candra" +, +"Candy" +, +"Caprice" +, +"Cara" +, +"Caralie" +, +"Caren" +, +"Carena" +, +"Caresa" +, +"Caressa" +, +"Caresse" +, +"Carey" +, +"Cari" +, +"Caria" +, +"Carie" +, +"Caril" +, +"Carilyn" +, +"Carin" +, +"Carina" +, +"Carine" +, +"Cariotta" +, +"Carissa" +, +"Carita" +, +"Caritta" +, +"Carla" +, +"Carlee" +, +"Carleen" +, +"Carlen" +, +"Carlene" +, +"Carley" +, +"Carlie" +, +"Carlin" +, +"Carlina" +, +"Carline" +, +"Carlita" +, +"Carlota" +, +"Carlotta" +, +"Carly" +, +"Carlye" +, +"Carlyn" +, +"Carlynn" +, +"Carlynne" +, +"Carma" +, +"Carmel" +, +"Carmela" +, +"Carmelia" +, +"Carmelina" +, +"Carmelita" +, +"Carmella" +, +"Carmelle" +, +"Carmen" +, +"Carmencita" +, +"Carmina" +, +"Carmine" +, +"Carmita" +, +"Carmon" +, +"Caro" +, +"Carol" +, +"Carol-Jean" +, +"Carola" +, +"Carolan" +, +"Carolann" +, +"Carole" +, +"Carolee" +, +"Carolin" +, +"Carolina" +, +"Caroline" +, +"Caroljean" +, +"Carolyn" +, +"Carolyne" +, +"Carolynn" +, +"Caron" +, +"Carree" +, +"Carri" +, +"Carrie" +, +"Carrissa" +, +"Carroll" +, +"Carry" +, +"Cary" +, +"Caryl" +, +"Caryn" +, +"Casandra" +, +"Casey" +, +"Casi" +, +"Casie" +, +"Cass" +, +"Cassandra" +, +"Cassandre" +, +"Cassandry" +, +"Cassaundra" +, +"Cassey" +, +"Cassi" +, +"Cassie" +, +"Cassondra" +, +"Cassy" +, +"Catarina" +, +"Cate" +, +"Caterina" +, +"Catha" +, +"Catharina" +, +"Catharine" +, +"Cathe" +, +"Cathee" +, +"Catherin" +, +"Catherina" +, +"Catherine" +, +"Cathi" +, +"Cathie" +, +"Cathleen" +, +"Cathlene" +, +"Cathrin" +, +"Cathrine" +, +"Cathryn" +, +"Cathy" +, +"Cathyleen" +, +"Cati" +, +"Catie" +, +"Catina" +, +"Catlaina" +, +"Catlee" +, +"Catlin" +, +"Catrina" +, +"Catriona" +, +"Caty" +, +"Caye" +, +"Cayla" +, +"Cecelia" +, +"Cecil" +, +"Cecile" +, +"Ceciley" +, +"Cecilia" +, +"Cecilla" +, +"Cecily" +, +"Ceil" +, +"Cele" +, +"Celene" +, +"Celesta" +, +"Celeste" +, +"Celestia" +, +"Celestina" +, +"Celestine" +, +"Celestyn" +, +"Celestyna" +, +"Celia" +, +"Celie" +, +"Celina" +, +"Celinda" +, +"Celine" +, +"Celinka" +, +"Celisse" +, +"Celka" +, +"Celle" +, +"Cesya" +, +"Chad" +, +"Chanda" +, +"Chandal" +, +"Chandra" +, +"Channa" +, +"Chantal" +, +"Chantalle" +, +"Charil" +, +"Charin" +, +"Charis" +, +"Charissa" +, +"Charisse" +, +"Charita" +, +"Charity" +, +"Charla" +, +"Charlean" +, +"Charleen" +, +"Charlena" +, +"Charlene" +, +"Charline" +, +"Charlot" +, +"Charlotta" +, +"Charlotte" +, +"Charmain" +, +"Charmaine" +, +"Charmane" +, +"Charmian" +, +"Charmine" +, +"Charmion" +, +"Charo" +, +"Charyl" +, +"Chastity" +, +"Chelsae" +, +"Chelsea" +, +"Chelsey" +, +"Chelsie" +, +"Chelsy" +, +"Cher" +, +"Chere" +, +"Cherey" +, +"Cheri" +, +"Cherianne" +, +"Cherice" +, +"Cherida" +, +"Cherie" +, +"Cherilyn" +, +"Cherilynn" +, +"Cherin" +, +"Cherise" +, +"Cherish" +, +"Cherlyn" +, +"Cherri" +, +"Cherrita" +, +"Cherry" +, +"Chery" +, +"Cherye" +, +"Cheryl" +, +"Cheslie" +, +"Chiarra" +, +"Chickie" +, +"Chicky" +, +"Chiquia" +, +"Chiquita" +, +"Chlo" +, +"Chloe" +, +"Chloette" +, +"Chloris" +, +"Chris" +, +"Chrissie" +, +"Chrissy" +, +"Christa" +, +"Christabel" +, +"Christabella" +, +"Christal" +, +"Christalle" +, +"Christan" +, +"Christean" +, +"Christel" +, +"Christen" +, +"Christi" +, +"Christian" +, +"Christiana" +, +"Christiane" +, +"Christie" +, +"Christin" +, +"Christina" +, +"Christine" +, +"Christy" +, +"Christye" +, +"Christyna" +, +"Chrysa" +, +"Chrysler" +, +"Chrystal" +, +"Chryste" +, +"Chrystel" +, +"Cicely" +, +"Cicily" +, +"Ciel" +, +"Cilka" +, +"Cinda" +, +"Cindee" +, +"Cindelyn" +, +"Cinderella" +, +"Cindi" +, +"Cindie" +, +"Cindra" +, +"Cindy" +, +"Cinnamon" +, +"Cissiee" +, +"Cissy" +, +"Clair" +, +"Claire" +, +"Clara" +, +"Clarabelle" +, +"Clare" +, +"Claresta" +, +"Clareta" +, +"Claretta" +, +"Clarette" +, +"Clarey" +, +"Clari" +, +"Claribel" +, +"Clarice" +, +"Clarie" +, +"Clarinda" +, +"Clarine" +, +"Clarissa" +, +"Clarisse" +, +"Clarita" +, +"Clary" +, +"Claude" +, +"Claudelle" +, +"Claudetta" +, +"Claudette" +, +"Claudia" +, +"Claudie" +, +"Claudina" +, +"Claudine" +, +"Clea" +, +"Clem" +, +"Clemence" +, +"Clementia" +, +"Clementina" +, +"Clementine" +, +"Clemmie" +, +"Clemmy" +, +"Cleo" +, +"Cleopatra" +, +"Clerissa" +, +"Clio" +, +"Clo" +, +"Cloe" +, +"Cloris" +, +"Clotilda" +, +"Clovis" +, +"Codee" +, +"Codi" +, +"Codie" +, +"Cody" +, +"Coleen" +, +"Colene" +, +"Coletta" +, +"Colette" +, +"Colleen" +, +"Collen" +, +"Collete" +, +"Collette" +, +"Collie" +, +"Colline" +, +"Colly" +, +"Con" +, +"Concettina" +, +"Conchita" +, +"Concordia" +, +"Conni" +, +"Connie" +, +"Conny" +, +"Consolata" +, +"Constance" +, +"Constancia" +, +"Constancy" +, +"Constanta" +, +"Constantia" +, +"Constantina" +, +"Constantine" +, +"Consuela" +, +"Consuelo" +, +"Cookie" +, +"Cora" +, +"Corabel" +, +"Corabella" +, +"Corabelle" +, +"Coral" +, +"Coralie" +, +"Coraline" +, +"Coralyn" +, +"Cordelia" +, +"Cordelie" +, +"Cordey" +, +"Cordi" +, +"Cordie" +, +"Cordula" +, +"Cordy" +, +"Coreen" +, +"Corella" +, +"Corenda" +, +"Corene" +, +"Coretta" +, +"Corette" +, +"Corey" +, +"Cori" +, +"Corie" +, +"Corilla" +, +"Corina" +, +"Corine" +, +"Corinna" +, +"Corinne" +, +"Coriss" +, +"Corissa" +, +"Corliss" +, +"Corly" +, +"Cornela" +, +"Cornelia" +, +"Cornelle" +, +"Cornie" +, +"Corny" +, +"Correna" +, +"Correy" +, +"Corri" +, +"Corrianne" +, +"Corrie" +, +"Corrina" +, +"Corrine" +, +"Corrinne" +, +"Corry" +, +"Cortney" +, +"Cory" +, +"Cosetta" +, +"Cosette" +, +"Costanza" +, +"Courtenay" +, +"Courtnay" +, +"Courtney" +, +"Crin" +, +"Cris" +, +"Crissie" +, +"Crissy" +, +"Crista" +, +"Cristabel" +, +"Cristal" +, +"Cristen" +, +"Cristi" +, +"Cristie" +, +"Cristin" +, +"Cristina" +, +"Cristine" +, +"Cristionna" +, +"Cristy" +, +"Crysta" +, +"Crystal" +, +"Crystie" +, +"Cthrine" +, +"Cyb" +, +"Cybil" +, +"Cybill" +, +"Cymbre" +, +"Cynde" +, +"Cyndi" +, +"Cyndia" +, +"Cyndie" +, +"Cyndy" +, +"Cynthea" +, +"Cynthia" +, +"Cynthie" +, +"Cynthy" +, +"Dacey" +, +"Dacia" +, +"Dacie" +, +"Dacy" +, +"Dael" +, +"Daffi" +, +"Daffie" +, +"Daffy" +, +"Dagmar" +, +"Dahlia" +, +"Daile" +, +"Daisey" +, +"Daisi" +, +"Daisie" +, +"Daisy" +, +"Dale" +, +"Dalenna" +, +"Dalia" +, +"Dalila" +, +"Dallas" +, +"Daloris" +, +"Damara" +, +"Damaris" +, +"Damita" +, +"Dana" +, +"Danell" +, +"Danella" +, +"Danette" +, +"Dani" +, +"Dania" +, +"Danica" +, +"Danice" +, +"Daniela" +, +"Daniele" +, +"Daniella" +, +"Danielle" +, +"Danika" +, +"Danila" +, +"Danit" +, +"Danita" +, +"Danna" +, +"Danni" +, +"Dannie" +, +"Danny" +, +"Dannye" +, +"Danya" +, +"Danyelle" +, +"Danyette" +, +"Daphene" +, +"Daphna" +, +"Daphne" +, +"Dara" +, +"Darb" +, +"Darbie" +, +"Darby" +, +"Darcee" +, +"Darcey" +, +"Darci" +, +"Darcie" +, +"Darcy" +, +"Darda" +, +"Dareen" +, +"Darell" +, +"Darelle" +, +"Dari" +, +"Daria" +, +"Darice" +, +"Darla" +, +"Darleen" +, +"Darlene" +, +"Darline" +, +"Darlleen" +, +"Daron" +, +"Darrelle" +, +"Darryl" +, +"Darsey" +, +"Darsie" +, +"Darya" +, +"Daryl" +, +"Daryn" +, +"Dasha" +, +"Dasi" +, +"Dasie" +, +"Dasya" +, +"Datha" +, +"Daune" +, +"Daveen" +, +"Daveta" +, +"Davida" +, +"Davina" +, +"Davine" +, +"Davita" +, +"Dawn" +, +"Dawna" +, +"Dayle" +, +"Dayna" +, +"Ddene" +, +"De" +, +"Deana" +, +"Deane" +, +"Deanna" +, +"Deanne" +, +"Deb" +, +"Debbi" +, +"Debbie" +, +"Debby" +, +"Debee" +, +"Debera" +, +"Debi" +, +"Debor" +, +"Debora" +, +"Deborah" +, +"Debra" +, +"Dede" +, +"Dedie" +, +"Dedra" +, +"Dee" +, +"Dee Dee" +, +"Deeann" +, +"Deeanne" +, +"Deedee" +, +"Deena" +, +"Deerdre" +, +"Deeyn" +, +"Dehlia" +, +"Deidre" +, +"Deina" +, +"Deirdre" +, +"Del" +, +"Dela" +, +"Delcina" +, +"Delcine" +, +"Delia" +, +"Delila" +, +"Delilah" +, +"Delinda" +, +"Dell" +, +"Della" +, +"Delly" +, +"Delora" +, +"Delores" +, +"Deloria" +, +"Deloris" +, +"Delphine" +, +"Delphinia" +, +"Demeter" +, +"Demetra" +, +"Demetria" +, +"Demetris" +, +"Dena" +, +"Deni" +, +"Denice" +, +"Denise" +, +"Denna" +, +"Denni" +, +"Dennie" +, +"Denny" +, +"Deny" +, +"Denys" +, +"Denyse" +, +"Deonne" +, +"Desdemona" +, +"Desirae" +, +"Desiree" +, +"Desiri" +, +"Deva" +, +"Devan" +, +"Devi" +, +"Devin" +, +"Devina" +, +"Devinne" +, +"Devon" +, +"Devondra" +, +"Devonna" +, +"Devonne" +, +"Devora" +, +"Di" +, +"Diahann" +, +"Dian" +, +"Diana" +, +"Diandra" +, +"Diane" +, +"Diane-Marie" +, +"Dianemarie" +, +"Diann" +, +"Dianna" +, +"Dianne" +, +"Diannne" +, +"Didi" +, +"Dido" +, +"Diena" +, +"Dierdre" +, +"Dina" +, +"Dinah" +, +"Dinnie" +, +"Dinny" +, +"Dion" +, +"Dione" +, +"Dionis" +, +"Dionne" +, +"Dita" +, +"Dix" +, +"Dixie" +, +"Dniren" +, +"Dode" +, +"Dodi" +, +"Dodie" +, +"Dody" +, +"Doe" +, +"Doll" +, +"Dolley" +, +"Dolli" +, +"Dollie" +, +"Dolly" +, +"Dolores" +, +"Dolorita" +, +"Doloritas" +, +"Domeniga" +, +"Dominga" +, +"Domini" +, +"Dominica" +, +"Dominique" +, +"Dona" +, +"Donella" +, +"Donelle" +, +"Donetta" +, +"Donia" +, +"Donica" +, +"Donielle" +, +"Donna" +, +"Donnamarie" +, +"Donni" +, +"Donnie" +, +"Donny" +, +"Dora" +, +"Doralia" +, +"Doralin" +, +"Doralyn" +, +"Doralynn" +, +"Doralynne" +, +"Dore" +, +"Doreen" +, +"Dorelia" +, +"Dorella" +, +"Dorelle" +, +"Dorena" +, +"Dorene" +, +"Doretta" +, +"Dorette" +, +"Dorey" +, +"Dori" +, +"Doria" +, +"Dorian" +, +"Dorice" +, +"Dorie" +, +"Dorine" +, +"Doris" +, +"Dorisa" +, +"Dorise" +, +"Dorita" +, +"Doro" +, +"Dorolice" +, +"Dorolisa" +, +"Dorotea" +, +"Doroteya" +, +"Dorothea" +, +"Dorothee" +, +"Dorothy" +, +"Dorree" +, +"Dorri" +, +"Dorrie" +, +"Dorris" +, +"Dorry" +, +"Dorthea" +, +"Dorthy" +, +"Dory" +, +"Dosi" +, +"Dot" +, +"Doti" +, +"Dotti" +, +"Dottie" +, +"Dotty" +, +"Dre" +, +"Dreddy" +, +"Dredi" +, +"Drona" +, +"Dru" +, +"Druci" +, +"Drucie" +, +"Drucill" +, +"Drucy" +, +"Drusi" +, +"Drusie" +, +"Drusilla" +, +"Drusy" +, +"Dulce" +, +"Dulcea" +, +"Dulci" +, +"Dulcia" +, +"Dulciana" +, +"Dulcie" +, +"Dulcine" +, +"Dulcinea" +, +"Dulcy" +, +"Dulsea" +, +"Dusty" +, +"Dyan" +, +"Dyana" +, +"Dyane" +, +"Dyann" +, +"Dyanna" +, +"Dyanne" +, +"Dyna" +, +"Dynah" +, +"Eachelle" +, +"Eada" +, +"Eadie" +, +"Eadith" +, +"Ealasaid" +, +"Eartha" +, +"Easter" +, +"Eba" +, +"Ebba" +, +"Ebonee" +, +"Ebony" +, +"Eda" +, +"Eddi" +, +"Eddie" +, +"Eddy" +, +"Ede" +, +"Edee" +, +"Edeline" +, +"Eden" +, +"Edi" +, +"Edie" +, +"Edin" +, +"Edita" +, +"Edith" +, +"Editha" +, +"Edithe" +, +"Ediva" +, +"Edna" +, +"Edwina" +, +"Edy" +, +"Edyth" +, +"Edythe" +, +"Effie" +, +"Eileen" +, +"Eilis" +, +"Eimile" +, +"Eirena" +, +"Ekaterina" +, +"Elaina" +, +"Elaine" +, +"Elana" +, +"Elane" +, +"Elayne" +, +"Elberta" +, +"Elbertina" +, +"Elbertine" +, +"Eleanor" +, +"Eleanora" +, +"Eleanore" +, +"Electra" +, +"Eleen" +, +"Elena" +, +"Elene" +, +"Eleni" +, +"Elenore" +, +"Eleonora" +, +"Eleonore" +, +"Elfie" +, +"Elfreda" +, +"Elfrida" +, +"Elfrieda" +, +"Elga" +, +"Elianora" +, +"Elianore" +, +"Elicia" +, +"Elie" +, +"Elinor" +, +"Elinore" +, +"Elisa" +, +"Elisabet" +, +"Elisabeth" +, +"Elisabetta" +, +"Elise" +, +"Elisha" +, +"Elissa" +, +"Elita" +, +"Eliza" +, +"Elizabet" +, +"Elizabeth" +, +"Elka" +, +"Elke" +, +"Ella" +, +"Elladine" +, +"Elle" +, +"Ellen" +, +"Ellene" +, +"Ellette" +, +"Elli" +, +"Ellie" +, +"Ellissa" +, +"Elly" +, +"Ellyn" +, +"Ellynn" +, +"Elmira" +, +"Elna" +, +"Elnora" +, +"Elnore" +, +"Eloisa" +, +"Eloise" +, +"Elonore" +, +"Elora" +, +"Elsa" +, +"Elsbeth" +, +"Else" +, +"Elset" +, +"Elsey" +, +"Elsi" +, +"Elsie" +, +"Elsinore" +, +"Elspeth" +, +"Elsy" +, +"Elva" +, +"Elvera" +, +"Elvina" +, +"Elvira" +, +"Elwira" +, +"Elyn" +, +"Elyse" +, +"Elysee" +, +"Elysha" +, +"Elysia" +, +"Elyssa" +, +"Em" +, +"Ema" +, +"Emalee" +, +"Emalia" +, +"Emelda" +, +"Emelia" +, +"Emelina" +, +"Emeline" +, +"Emelita" +, +"Emelyne" +, +"Emera" +, +"Emilee" +, +"Emili" +, +"Emilia" +, +"Emilie" +, +"Emiline" +, +"Emily" +, +"Emlyn" +, +"Emlynn" +, +"Emlynne" +, +"Emma" +, +"Emmalee" +, +"Emmaline" +, +"Emmalyn" +, +"Emmalynn" +, +"Emmalynne" +, +"Emmeline" +, +"Emmey" +, +"Emmi" +, +"Emmie" +, +"Emmy" +, +"Emmye" +, +"Emogene" +, +"Emyle" +, +"Emylee" +, +"Engracia" +, +"Enid" +, +"Enrica" +, +"Enrichetta" +, +"Enrika" +, +"Enriqueta" +, +"Eolanda" +, +"Eolande" +, +"Eran" +, +"Erda" +, +"Erena" +, +"Erica" +, +"Ericha" +, +"Ericka" +, +"Erika" +, +"Erin" +, +"Erina" +, +"Erinn" +, +"Erinna" +, +"Erma" +, +"Ermengarde" +, +"Ermentrude" +, +"Ermina" +, +"Erminia" +, +"Erminie" +, +"Erna" +, +"Ernaline" +, +"Ernesta" +, +"Ernestine" +, +"Ertha" +, +"Eryn" +, +"Esma" +, +"Esmaria" +, +"Esme" +, +"Esmeralda" +, +"Essa" +, +"Essie" +, +"Essy" +, +"Esta" +, +"Estel" +, +"Estele" +, +"Estell" +, +"Estella" +, +"Estelle" +, +"Ester" +, +"Esther" +, +"Estrella" +, +"Estrellita" +, +"Ethel" +, +"Ethelda" +, +"Ethelin" +, +"Ethelind" +, +"Etheline" +, +"Ethelyn" +, +"Ethyl" +, +"Etta" +, +"Etti" +, +"Ettie" +, +"Etty" +, +"Eudora" +, +"Eugenia" +, +"Eugenie" +, +"Eugine" +, +"Eula" +, +"Eulalie" +, +"Eunice" +, +"Euphemia" +, +"Eustacia" +, +"Eva" +, +"Evaleen" +, +"Evangelia" +, +"Evangelin" +, +"Evangelina" +, +"Evangeline" +, +"Evania" +, +"Evanne" +, +"Eve" +, +"Eveleen" +, +"Evelina" +, +"Eveline" +, +"Evelyn" +, +"Evey" +, +"Evie" +, +"Evita" +, +"Evonne" +, +"Evvie" +, +"Evvy" +, +"Evy" +, +"Eyde" +, +"Eydie" +, +"Ezmeralda" +, +"Fae" +, +"Faina" +, +"Faith" +, +"Fallon" +, +"Fan" +, +"Fanchette" +, +"Fanchon" +, +"Fancie" +, +"Fancy" +, +"Fanechka" +, +"Fania" +, +"Fanni" +, +"Fannie" +, +"Fanny" +, +"Fanya" +, +"Fara" +, +"Farah" +, +"Farand" +, +"Farica" +, +"Farra" +, +"Farrah" +, +"Farrand" +, +"Faun" +, +"Faunie" +, +"Faustina" +, +"Faustine" +, +"Fawn" +, +"Fawne" +, +"Fawnia" +, +"Fay" +, +"Faydra" +, +"Faye" +, +"Fayette" +, +"Fayina" +, +"Fayre" +, +"Fayth" +, +"Faythe" +, +"Federica" +, +"Fedora" +, +"Felecia" +, +"Felicdad" +, +"Felice" +, +"Felicia" +, +"Felicity" +, +"Felicle" +, +"Felipa" +, +"Felisha" +, +"Felita" +, +"Feliza" +, +"Fenelia" +, +"Feodora" +, +"Ferdinanda" +, +"Ferdinande" +, +"Fern" +, +"Fernanda" +, +"Fernande" +, +"Fernandina" +, +"Ferne" +, +"Fey" +, +"Fiann" +, +"Fianna" +, +"Fidela" +, +"Fidelia" +, +"Fidelity" +, +"Fifi" +, +"Fifine" +, +"Filia" +, +"Filide" +, +"Filippa" +, +"Fina" +, +"Fiona" +, +"Fionna" +, +"Fionnula" +, +"Fiorenze" +, +"Fleur" +, +"Fleurette" +, +"Flo" +, +"Flor" +, +"Flora" +, +"Florance" +, +"Flore" +, +"Florella" +, +"Florence" +, +"Florencia" +, +"Florentia" +, +"Florenza" +, +"Florette" +, +"Flori" +, +"Floria" +, +"Florida" +, +"Florie" +, +"Florina" +, +"Florinda" +, +"Floris" +, +"Florri" +, +"Florrie" +, +"Florry" +, +"Flory" +, +"Flossi" +, +"Flossie" +, +"Flossy" +, +"Flss" +, +"Fran" +, +"Francene" +, +"Frances" +, +"Francesca" +, +"Francine" +, +"Francisca" +, +"Franciska" +, +"Francoise" +, +"Francyne" +, +"Frank" +, +"Frankie" +, +"Franky" +, +"Franni" +, +"Frannie" +, +"Franny" +, +"Frayda" +, +"Fred" +, +"Freda" +, +"Freddi" +, +"Freddie" +, +"Freddy" +, +"Fredelia" +, +"Frederica" +, +"Fredericka" +, +"Frederique" +, +"Fredi" +, +"Fredia" +, +"Fredra" +, +"Fredrika" +, +"Freida" +, +"Frieda" +, +"Friederike" +, +"Fulvia" +, +"Gabbey" +, +"Gabbi" +, +"Gabbie" +, +"Gabey" +, +"Gabi" +, +"Gabie" +, +"Gabriel" +, +"Gabriela" +, +"Gabriell" +, +"Gabriella" +, +"Gabrielle" +, +"Gabriellia" +, +"Gabrila" +, +"Gaby" +, +"Gae" +, +"Gael" +, +"Gail" +, +"Gale" +, +"Gale" +, +"Galina" +, +"Garland" +, +"Garnet" +, +"Garnette" +, +"Gates" +, +"Gavra" +, +"Gavrielle" +, +"Gay" +, +"Gaye" +, +"Gayel" +, +"Gayla" +, +"Gayle" +, +"Gayleen" +, +"Gaylene" +, +"Gaynor" +, +"Gelya" +, +"Gena" +, +"Gene" +, +"Geneva" +, +"Genevieve" +, +"Genevra" +, +"Genia" +, +"Genna" +, +"Genni" +, +"Gennie" +, +"Gennifer" +, +"Genny" +, +"Genovera" +, +"Genvieve" +, +"George" +, +"Georgeanna" +, +"Georgeanne" +, +"Georgena" +, +"Georgeta" +, +"Georgetta" +, +"Georgette" +, +"Georgia" +, +"Georgiana" +, +"Georgianna" +, +"Georgianne" +, +"Georgie" +, +"Georgina" +, +"Georgine" +, +"Geralda" +, +"Geraldine" +, +"Gerda" +, +"Gerhardine" +, +"Geri" +, +"Gerianna" +, +"Gerianne" +, +"Gerladina" +, +"Germain" +, +"Germaine" +, +"Germana" +, +"Gerri" +, +"Gerrie" +, +"Gerrilee" +, +"Gerry" +, +"Gert" +, +"Gerta" +, +"Gerti" +, +"Gertie" +, +"Gertrud" +, +"Gertruda" +, +"Gertrude" +, +"Gertrudis" +, +"Gerty" +, +"Giacinta" +, +"Giana" +, +"Gianina" +, +"Gianna" +, +"Gigi" +, +"Gilberta" +, +"Gilberte" +, +"Gilbertina" +, +"Gilbertine" +, +"Gilda" +, +"Gilemette" +, +"Gill" +, +"Gillan" +, +"Gilli" +, +"Gillian" +, +"Gillie" +, +"Gilligan" +, +"Gilly" +, +"Gina" +, +"Ginelle" +, +"Ginevra" +, +"Ginger" +, +"Ginni" +, +"Ginnie" +, +"Ginnifer" +, +"Ginny" +, +"Giorgia" +, +"Giovanna" +, +"Gipsy" +, +"Giralda" +, +"Gisela" +, +"Gisele" +, +"Gisella" +, +"Giselle" +, +"Giuditta" +, +"Giulia" +, +"Giulietta" +, +"Giustina" +, +"Gizela" +, +"Glad" +, +"Gladi" +, +"Gladys" +, +"Gleda" +, +"Glen" +, +"Glenda" +, +"Glenine" +, +"Glenn" +, +"Glenna" +, +"Glennie" +, +"Glennis" +, +"Glori" +, +"Gloria" +, +"Gloriana" +, +"Gloriane" +, +"Glory" +, +"Glyn" +, +"Glynda" +, +"Glynis" +, +"Glynnis" +, +"Gnni" +, +"Godiva" +, +"Golda" +, +"Goldarina" +, +"Goldi" +, +"Goldia" +, +"Goldie" +, +"Goldina" +, +"Goldy" +, +"Grace" +, +"Gracia" +, +"Gracie" +, +"Grata" +, +"Gratia" +, +"Gratiana" +, +"Gray" +, +"Grayce" +, +"Grazia" +, +"Greer" +, +"Greta" +, +"Gretal" +, +"Gretchen" +, +"Grete" +, +"Gretel" +, +"Grethel" +, +"Gretna" +, +"Gretta" +, +"Grier" +, +"Griselda" +, +"Grissel" +, +"Guendolen" +, +"Guenevere" +, +"Guenna" +, +"Guglielma" +, +"Gui" +, +"Guillema" +, +"Guillemette" +, +"Guinevere" +, +"Guinna" +, +"Gunilla" +, +"Gus" +, +"Gusella" +, +"Gussi" +, +"Gussie" +, +"Gussy" +, +"Gusta" +, +"Gusti" +, +"Gustie" +, +"Gusty" +, +"Gwen" +, +"Gwendolen" +, +"Gwendolin" +, +"Gwendolyn" +, +"Gweneth" +, +"Gwenette" +, +"Gwenneth" +, +"Gwenni" +, +"Gwennie" +, +"Gwenny" +, +"Gwenora" +, +"Gwenore" +, +"Gwyn" +, +"Gwyneth" +, +"Gwynne" +, +"Gypsy" +, +"Hadria" +, +"Hailee" +, +"Haily" +, +"Haleigh" +, +"Halette" +, +"Haley" +, +"Hali" +, +"Halie" +, +"Halimeda" +, +"Halley" +, +"Halli" +, +"Hallie" +, +"Hally" +, +"Hana" +, +"Hanna" +, +"Hannah" +, +"Hanni" +, +"Hannie" +, +"Hannis" +, +"Hanny" +, +"Happy" +, +"Harlene" +, +"Harley" +, +"Harli" +, +"Harlie" +, +"Harmonia" +, +"Harmonie" +, +"Harmony" +, +"Harri" +, +"Harrie" +, +"Harriet" +, +"Harriett" +, +"Harrietta" +, +"Harriette" +, +"Harriot" +, +"Harriott" +, +"Hatti" +, +"Hattie" +, +"Hatty" +, +"Hayley" +, +"Hazel" +, +"Heath" +, +"Heather" +, +"Heda" +, +"Hedda" +, +"Heddi" +, +"Heddie" +, +"Hedi" +, +"Hedvig" +, +"Hedvige" +, +"Hedwig" +, +"Hedwiga" +, +"Hedy" +, +"Heida" +, +"Heidi" +, +"Heidie" +, +"Helaina" +, +"Helaine" +, +"Helen" +, +"Helen-Elizabeth" +, +"Helena" +, +"Helene" +, +"Helenka" +, +"Helga" +, +"Helge" +, +"Helli" +, +"Heloise" +, +"Helsa" +, +"Helyn" +, +"Hendrika" +, +"Henka" +, +"Henrie" +, +"Henrieta" +, +"Henrietta" +, +"Henriette" +, +"Henryetta" +, +"Hephzibah" +, +"Hermia" +, +"Hermina" +, +"Hermine" +, +"Herminia" +, +"Hermione" +, +"Herta" +, +"Hertha" +, +"Hester" +, +"Hesther" +, +"Hestia" +, +"Hetti" +, +"Hettie" +, +"Hetty" +, +"Hilary" +, +"Hilda" +, +"Hildagard" +, +"Hildagarde" +, +"Hilde" +, +"Hildegaard" +, +"Hildegarde" +, +"Hildy" +, +"Hillary" +, +"Hilliary" +, +"Hinda" +, +"Holli" +, +"Hollie" +, +"Holly" +, +"Holly-Anne" +, +"Hollyanne" +, +"Honey" +, +"Honor" +, +"Honoria" +, +"Hope" +, +"Horatia" +, +"Hortense" +, +"Hortensia" +, +"Hulda" +, +"Hyacinth" +, +"Hyacintha" +, +"Hyacinthe" +, +"Hyacinthia" +, +"Hyacinthie" +, +"Hynda" +, +"Ianthe" +, +"Ibbie" +, +"Ibby" +, +"Ida" +, +"Idalia" +, +"Idalina" +, +"Idaline" +, +"Idell" +, +"Idelle" +, +"Idette" +, +"Ileana" +, +"Ileane" +, +"Ilene" +, +"Ilise" +, +"Ilka" +, +"Illa" +, +"Ilsa" +, +"Ilse" +, +"Ilysa" +, +"Ilyse" +, +"Ilyssa" +, +"Imelda" +, +"Imogen" +, +"Imogene" +, +"Imojean" +, +"Ina" +, +"Indira" +, +"Ines" +, +"Inesita" +, +"Inessa" +, +"Inez" +, +"Inga" +, +"Ingaberg" +, +"Ingaborg" +, +"Inge" +, +"Ingeberg" +, +"Ingeborg" +, +"Inger" +, +"Ingrid" +, +"Ingunna" +, +"Inna" +, +"Iolande" +, +"Iolanthe" +, +"Iona" +, +"Iormina" +, +"Ira" +, +"Irena" +, +"Irene" +, +"Irina" +, +"Iris" +, +"Irita" +, +"Irma" +, +"Isa" +, +"Isabel" +, +"Isabelita" +, +"Isabella" +, +"Isabelle" +, +"Isadora" +, +"Isahella" +, +"Iseabal" +, +"Isidora" +, +"Isis" +, +"Isobel" +, +"Issi" +, +"Issie" +, +"Issy" +, +"Ivett" +, +"Ivette" +, +"Ivie" +, +"Ivonne" +, +"Ivory" +, +"Ivy" +, +"Izabel" +, +"Jacenta" +, +"Jacinda" +, +"Jacinta" +, +"Jacintha" +, +"Jacinthe" +, +"Jackelyn" +, +"Jacki" +, +"Jackie" +, +"Jacklin" +, +"Jacklyn" +, +"Jackquelin" +, +"Jackqueline" +, +"Jacky" +, +"Jaclin" +, +"Jaclyn" +, +"Jacquelin" +, +"Jacqueline" +, +"Jacquelyn" +, +"Jacquelynn" +, +"Jacquenetta" +, +"Jacquenette" +, +"Jacquetta" +, +"Jacquette" +, +"Jacqui" +, +"Jacquie" +, +"Jacynth" +, +"Jada" +, +"Jade" +, +"Jaime" +, +"Jaimie" +, +"Jaine" +, +"Jami" +, +"Jamie" +, +"Jamima" +, +"Jammie" +, +"Jan" +, +"Jana" +, +"Janaya" +, +"Janaye" +, +"Jandy" +, +"Jane" +, +"Janean" +, +"Janeczka" +, +"Janeen" +, +"Janel" +, +"Janela" +, +"Janella" +, +"Janelle" +, +"Janene" +, +"Janenna" +, +"Janessa" +, +"Janet" +, +"Janeta" +, +"Janetta" +, +"Janette" +, +"Janeva" +, +"Janey" +, +"Jania" +, +"Janice" +, +"Janie" +, +"Janifer" +, +"Janina" +, +"Janine" +, +"Janis" +, +"Janith" +, +"Janka" +, +"Janna" +, +"Jannel" +, +"Jannelle" +, +"Janot" +, +"Jany" +, +"Jaquelin" +, +"Jaquelyn" +, +"Jaquenetta" +, +"Jaquenette" +, +"Jaquith" +, +"Jasmin" +, +"Jasmina" +, +"Jasmine" +, +"Jayme" +, +"Jaymee" +, +"Jayne" +, +"Jaynell" +, +"Jazmin" +, +"Jean" +, +"Jeana" +, +"Jeane" +, +"Jeanelle" +, +"Jeanette" +, +"Jeanie" +, +"Jeanine" +, +"Jeanna" +, +"Jeanne" +, +"Jeannette" +, +"Jeannie" +, +"Jeannine" +, +"Jehanna" +, +"Jelene" +, +"Jemie" +, +"Jemima" +, +"Jemimah" +, +"Jemmie" +, +"Jemmy" +, +"Jen" +, +"Jena" +, +"Jenda" +, +"Jenelle" +, +"Jeni" +, +"Jenica" +, +"Jeniece" +, +"Jenifer" +, +"Jeniffer" +, +"Jenilee" +, +"Jenine" +, +"Jenn" +, +"Jenna" +, +"Jennee" +, +"Jennette" +, +"Jenni" +, +"Jennica" +, +"Jennie" +, +"Jennifer" +, +"Jennilee" +, +"Jennine" +, +"Jenny" +, +"Jeralee" +, +"Jere" +, +"Jeri" +, +"Jermaine" +, +"Jerrie" +, +"Jerrilee" +, +"Jerrilyn" +, +"Jerrine" +, +"Jerry" +, +"Jerrylee" +, +"Jess" +, +"Jessa" +, +"Jessalin" +, +"Jessalyn" +, +"Jessamine" +, +"Jessamyn" +, +"Jesse" +, +"Jesselyn" +, +"Jessi" +, +"Jessica" +, +"Jessie" +, +"Jessika" +, +"Jessy" +, +"Jewel" +, +"Jewell" +, +"Jewelle" +, +"Jill" +, +"Jillana" +, +"Jillane" +, +"Jillayne" +, +"Jilleen" +, +"Jillene" +, +"Jilli" +, +"Jillian" +, +"Jillie" +, +"Jilly" +, +"Jinny" +, +"Jo" +, +"Jo Ann" +, +"Jo-Ann" +, +"Jo-Anne" +, +"Joan" +, +"Joana" +, +"Joane" +, +"Joanie" +, +"Joann" +, +"Joanna" +, +"Joanne" +, +"Joannes" +, +"Jobey" +, +"Jobi" +, +"Jobie" +, +"Jobina" +, +"Joby" +, +"Jobye" +, +"Jobyna" +, +"Jocelin" +, +"Joceline" +, +"Jocelyn" +, +"Jocelyne" +, +"Jodee" +, +"Jodi" +, +"Jodie" +, +"Jody" +, +"Joeann" +, +"Joela" +, +"Joelie" +, +"Joell" +, +"Joella" +, +"Joelle" +, +"Joellen" +, +"Joelly" +, +"Joellyn" +, +"Joelynn" +, +"Joete" +, +"Joey" +, +"Johanna" +, +"Johannah" +, +"Johna" +, +"Johnath" +, +"Johnette" +, +"Johnna" +, +"Joice" +, +"Jojo" +, +"Jolee" +, +"Joleen" +, +"Jolene" +, +"Joletta" +, +"Joli" +, +"Jolie" +, +"Joline" +, +"Joly" +, +"Jolyn" +, +"Jolynn" +, +"Jonell" +, +"Joni" +, +"Jonie" +, +"Jonis" +, +"Jordain" +, +"Jordan" +, +"Jordana" +, +"Jordanna" +, +"Jorey" +, +"Jori" +, +"Jorie" +, +"Jorrie" +, +"Jorry" +, +"Joscelin" +, +"Josee" +, +"Josefa" +, +"Josefina" +, +"Josepha" +, +"Josephina" +, +"Josephine" +, +"Josey" +, +"Josi" +, +"Josie" +, +"Josselyn" +, +"Josy" +, +"Jourdan" +, +"Joy" +, +"Joya" +, +"Joyan" +, +"Joyann" +, +"Joyce" +, +"Joycelin" +, +"Joye" +, +"Jsandye" +, +"Juana" +, +"Juanita" +, +"Judi" +, +"Judie" +, +"Judith" +, +"Juditha" +, +"Judy" +, +"Judye" +, +"Juieta" +, +"Julee" +, +"Juli" +, +"Julia" +, +"Juliana" +, +"Juliane" +, +"Juliann" +, +"Julianna" +, +"Julianne" +, +"Julie" +, +"Julienne" +, +"Juliet" +, +"Julieta" +, +"Julietta" +, +"Juliette" +, +"Julina" +, +"Juline" +, +"Julissa" +, +"Julita" +, +"June" +, +"Junette" +, +"Junia" +, +"Junie" +, +"Junina" +, +"Justina" +, +"Justine" +, +"Justinn" +, +"Jyoti" +, +"Kacey" +, +"Kacie" +, +"Kacy" +, +"Kaela" +, +"Kai" +, +"Kaia" +, +"Kaila" +, +"Kaile" +, +"Kailey" +, +"Kaitlin" +, +"Kaitlyn" +, +"Kaitlynn" +, +"Kaja" +, +"Kakalina" +, +"Kala" +, +"Kaleena" +, +"Kali" +, +"Kalie" +, +"Kalila" +, +"Kalina" +, +"Kalinda" +, +"Kalindi" +, +"Kalli" +, +"Kally" +, +"Kameko" +, +"Kamila" +, +"Kamilah" +, +"Kamillah" +, +"Kandace" +, +"Kandy" +, +"Kania" +, +"Kanya" +, +"Kara" +, +"Kara-Lynn" +, +"Karalee" +, +"Karalynn" +, +"Kare" +, +"Karee" +, +"Karel" +, +"Karen" +, +"Karena" +, +"Kari" +, +"Karia" +, +"Karie" +, +"Karil" +, +"Karilynn" +, +"Karin" +, +"Karina" +, +"Karine" +, +"Kariotta" +, +"Karisa" +, +"Karissa" +, +"Karita" +, +"Karla" +, +"Karlee" +, +"Karleen" +, +"Karlen" +, +"Karlene" +, +"Karlie" +, +"Karlotta" +, +"Karlotte" +, +"Karly" +, +"Karlyn" +, +"Karmen" +, +"Karna" +, +"Karol" +, +"Karola" +, +"Karole" +, +"Karolina" +, +"Karoline" +, +"Karoly" +, +"Karon" +, +"Karrah" +, +"Karrie" +, +"Karry" +, +"Kary" +, +"Karyl" +, +"Karylin" +, +"Karyn" +, +"Kasey" +, +"Kass" +, +"Kassandra" +, +"Kassey" +, +"Kassi" +, +"Kassia" +, +"Kassie" +, +"Kat" +, +"Kata" +, +"Katalin" +, +"Kate" +, +"Katee" +, +"Katerina" +, +"Katerine" +, +"Katey" +, +"Kath" +, +"Katha" +, +"Katharina" +, +"Katharine" +, +"Katharyn" +, +"Kathe" +, +"Katherina" +, +"Katherine" +, +"Katheryn" +, +"Kathi" +, +"Kathie" +, +"Kathleen" +, +"Kathlin" +, +"Kathrine" +, +"Kathryn" +, +"Kathryne" +, +"Kathy" +, +"Kathye" +, +"Kati" +, +"Katie" +, +"Katina" +, +"Katine" +, +"Katinka" +, +"Katleen" +, +"Katlin" +, +"Katrina" +, +"Katrine" +, +"Katrinka" +, +"Katti" +, +"Kattie" +, +"Katuscha" +, +"Katusha" +, +"Katy" +, +"Katya" +, +"Kay" +, +"Kaycee" +, +"Kaye" +, +"Kayla" +, +"Kayle" +, +"Kaylee" +, +"Kayley" +, +"Kaylil" +, +"Kaylyn" +, +"Keeley" +, +"Keelia" +, +"Keely" +, +"Kelcey" +, +"Kelci" +, +"Kelcie" +, +"Kelcy" +, +"Kelila" +, +"Kellen" +, +"Kelley" +, +"Kelli" +, +"Kellia" +, +"Kellie" +, +"Kellina" +, +"Kellsie" +, +"Kelly" +, +"Kellyann" +, +"Kelsey" +, +"Kelsi" +, +"Kelsy" +, +"Kendra" +, +"Kendre" +, +"Kenna" +, +"Keri" +, +"Keriann" +, +"Kerianne" +, +"Kerri" +, +"Kerrie" +, +"Kerrill" +, +"Kerrin" +, +"Kerry" +, +"Kerstin" +, +"Kesley" +, +"Keslie" +, +"Kessia" +, +"Kessiah" +, +"Ketti" +, +"Kettie" +, +"Ketty" +, +"Kevina" +, +"Kevyn" +, +"Ki" +, +"Kiah" +, +"Kial" +, +"Kiele" +, +"Kiersten" +, +"Kikelia" +, +"Kiley" +, +"Kim" +, +"Kimberlee" +, +"Kimberley" +, +"Kimberli" +, +"Kimberly" +, +"Kimberlyn" +, +"Kimbra" +, +"Kimmi" +, +"Kimmie" +, +"Kimmy" +, +"Kinna" +, +"Kip" +, +"Kipp" +, +"Kippie" +, +"Kippy" +, +"Kira" +, +"Kirbee" +, +"Kirbie" +, +"Kirby" +, +"Kiri" +, +"Kirsten" +, +"Kirsteni" +, +"Kirsti" +, +"Kirstin" +, +"Kirstyn" +, +"Kissee" +, +"Kissiah" +, +"Kissie" +, +"Kit" +, +"Kitti" +, +"Kittie" +, +"Kitty" +, +"Kizzee" +, +"Kizzie" +, +"Klara" +, +"Klarika" +, +"Klarrisa" +, +"Konstance" +, +"Konstanze" +, +"Koo" +, +"Kora" +, +"Koral" +, +"Koralle" +, +"Kordula" +, +"Kore" +, +"Korella" +, +"Koren" +, +"Koressa" +, +"Kori" +, +"Korie" +, +"Korney" +, +"Korrie" +, +"Korry" +, +"Kris" +, +"Krissie" +, +"Krissy" +, +"Krista" +, +"Kristal" +, +"Kristan" +, +"Kriste" +, +"Kristel" +, +"Kristen" +, +"Kristi" +, +"Kristien" +, +"Kristin" +, +"Kristina" +, +"Kristine" +, +"Kristy" +, +"Kristyn" +, +"Krysta" +, +"Krystal" +, +"Krystalle" +, +"Krystle" +, +"Krystyna" +, +"Kyla" +, +"Kyle" +, +"Kylen" +, +"Kylie" +, +"Kylila" +, +"Kylynn" +, +"Kym" +, +"Kynthia" +, +"Kyrstin" +, +"La Verne" +, +"Lacee" +, +"Lacey" +, +"Lacie" +, +"Lacy" +, +"Ladonna" +, +"Laetitia" +, +"Laina" +, +"Lainey" +, +"Lana" +, +"Lanae" +, +"Lane" +, +"Lanette" +, +"Laney" +, +"Lani" +, +"Lanie" +, +"Lanita" +, +"Lanna" +, +"Lanni" +, +"Lanny" +, +"Lara" +, +"Laraine" +, +"Lari" +, +"Larina" +, +"Larine" +, +"Larisa" +, +"Larissa" +, +"Lark" +, +"Laryssa" +, +"Latashia" +, +"Latia" +, +"Latisha" +, +"Latrena" +, +"Latrina" +, +"Laura" +, +"Lauraine" +, +"Laural" +, +"Lauralee" +, +"Laure" +, +"Lauree" +, +"Laureen" +, +"Laurel" +, +"Laurella" +, +"Lauren" +, +"Laurena" +, +"Laurene" +, +"Lauretta" +, +"Laurette" +, +"Lauri" +, +"Laurianne" +, +"Laurice" +, +"Laurie" +, +"Lauryn" +, +"Lavena" +, +"Laverna" +, +"Laverne" +, +"Lavina" +, +"Lavinia" +, +"Lavinie" +, +"Layla" +, +"Layne" +, +"Layney" +, +"Lea" +, +"Leah" +, +"Leandra" +, +"Leann" +, +"Leanna" +, +"Leanor" +, +"Leanora" +, +"Lebbie" +, +"Leda" +, +"Lee" +, +"Leeann" +, +"Leeanne" +, +"Leela" +, +"Leelah" +, +"Leena" +, +"Leesa" +, +"Leese" +, +"Legra" +, +"Leia" +, +"Leigh" +, +"Leigha" +, +"Leila" +, +"Leilah" +, +"Leisha" +, +"Lela" +, +"Lelah" +, +"Leland" +, +"Lelia" +, +"Lena" +, +"Lenee" +, +"Lenette" +, +"Lenka" +, +"Lenna" +, +"Lenora" +, +"Lenore" +, +"Leodora" +, +"Leoine" +, +"Leola" +, +"Leoline" +, +"Leona" +, +"Leonanie" +, +"Leone" +, +"Leonelle" +, +"Leonie" +, +"Leonora" +, +"Leonore" +, +"Leontine" +, +"Leontyne" +, +"Leora" +, +"Leshia" +, +"Lesley" +, +"Lesli" +, +"Leslie" +, +"Lesly" +, +"Lesya" +, +"Leta" +, +"Lethia" +, +"Leticia" +, +"Letisha" +, +"Letitia" +, +"Letizia" +, +"Letta" +, +"Letti" +, +"Lettie" +, +"Letty" +, +"Lexi" +, +"Lexie" +, +"Lexine" +, +"Lexis" +, +"Lexy" +, +"Leyla" +, +"Lezlie" +, +"Lia" +, +"Lian" +, +"Liana" +, +"Liane" +, +"Lianna" +, +"Lianne" +, +"Lib" +, +"Libbey" +, +"Libbi" +, +"Libbie" +, +"Libby" +, +"Licha" +, +"Lida" +, +"Lidia" +, +"Liesa" +, +"Lil" +, +"Lila" +, +"Lilah" +, +"Lilas" +, +"Lilia" +, +"Lilian" +, +"Liliane" +, +"Lilias" +, +"Lilith" +, +"Lilla" +, +"Lilli" +, +"Lillian" +, +"Lillis" +, +"Lilllie" +, +"Lilly" +, +"Lily" +, +"Lilyan" +, +"Lin" +, +"Lina" +, +"Lind" +, +"Linda" +, +"Lindi" +, +"Lindie" +, +"Lindsay" +, +"Lindsey" +, +"Lindsy" +, +"Lindy" +, +"Linea" +, +"Linell" +, +"Linet" +, +"Linette" +, +"Linn" +, +"Linnea" +, +"Linnell" +, +"Linnet" +, +"Linnie" +, +"Linzy" +, +"Lira" +, +"Lisa" +, +"Lisabeth" +, +"Lisbeth" +, +"Lise" +, +"Lisetta" +, +"Lisette" +, +"Lisha" +, +"Lishe" +, +"Lissa" +, +"Lissi" +, +"Lissie" +, +"Lissy" +, +"Lita" +, +"Liuka" +, +"Liv" +, +"Liva" +, +"Livia" +, +"Livvie" +, +"Livvy" +, +"Livvyy" +, +"Livy" +, +"Liz" +, +"Liza" +, +"Lizabeth" +, +"Lizbeth" +, +"Lizette" +, +"Lizzie" +, +"Lizzy" +, +"Loella" +, +"Lois" +, +"Loise" +, +"Lola" +, +"Loleta" +, +"Lolita" +, +"Lolly" +, +"Lona" +, +"Lonee" +, +"Loni" +, +"Lonna" +, +"Lonni" +, +"Lonnie" +, +"Lora" +, +"Lorain" +, +"Loraine" +, +"Loralee" +, +"Loralie" +, +"Loralyn" +, +"Loree" +, +"Loreen" +, +"Lorelei" +, +"Lorelle" +, +"Loren" +, +"Lorena" +, +"Lorene" +, +"Lorenza" +, +"Loretta" +, +"Lorette" +, +"Lori" +, +"Loria" +, +"Lorianna" +, +"Lorianne" +, +"Lorie" +, +"Lorilee" +, +"Lorilyn" +, +"Lorinda" +, +"Lorine" +, +"Lorita" +, +"Lorna" +, +"Lorne" +, +"Lorraine" +, +"Lorrayne" +, +"Lorri" +, +"Lorrie" +, +"Lorrin" +, +"Lorry" +, +"Lory" +, +"Lotta" +, +"Lotte" +, +"Lotti" +, +"Lottie" +, +"Lotty" +, +"Lou" +, +"Louella" +, +"Louisa" +, +"Louise" +, +"Louisette" +, +"Loutitia" +, +"Lu" +, +"Luce" +, +"Luci" +, +"Lucia" +, +"Luciana" +, +"Lucie" +, +"Lucienne" +, +"Lucila" +, +"Lucilia" +, +"Lucille" +, +"Lucina" +, +"Lucinda" +, +"Lucine" +, +"Lucita" +, +"Lucky" +, +"Lucretia" +, +"Lucy" +, +"Ludovika" +, +"Luella" +, +"Luelle" +, +"Luisa" +, +"Luise" +, +"Lula" +, +"Lulita" +, +"Lulu" +, +"Lura" +, +"Lurette" +, +"Lurleen" +, +"Lurlene" +, +"Lurline" +, +"Lusa" +, +"Luz" +, +"Lyda" +, +"Lydia" +, +"Lydie" +, +"Lyn" +, +"Lynda" +, +"Lynde" +, +"Lyndel" +, +"Lyndell" +, +"Lyndsay" +, +"Lyndsey" +, +"Lyndsie" +, +"Lyndy" +, +"Lynea" +, +"Lynelle" +, +"Lynett" +, +"Lynette" +, +"Lynn" +, +"Lynna" +, +"Lynne" +, +"Lynnea" +, +"Lynnell" +, +"Lynnelle" +, +"Lynnet" +, +"Lynnett" +, +"Lynnette" +, +"Lynsey" +, +"Lyssa" +, +"Mab" +, +"Mabel" +, +"Mabelle" +, +"Mable" +, +"Mada" +, +"Madalena" +, +"Madalyn" +, +"Maddalena" +, +"Maddi" +, +"Maddie" +, +"Maddy" +, +"Madel" +, +"Madelaine" +, +"Madeleine" +, +"Madelena" +, +"Madelene" +, +"Madelin" +, +"Madelina" +, +"Madeline" +, +"Madella" +, +"Madelle" +, +"Madelon" +, +"Madelyn" +, +"Madge" +, +"Madlen" +, +"Madlin" +, +"Madonna" +, +"Mady" +, +"Mae" +, +"Maegan" +, +"Mag" +, +"Magda" +, +"Magdaia" +, +"Magdalen" +, +"Magdalena" +, +"Magdalene" +, +"Maggee" +, +"Maggi" +, +"Maggie" +, +"Maggy" +, +"Mahala" +, +"Mahalia" +, +"Maia" +, +"Maible" +, +"Maiga" +, +"Maighdiln" +, +"Mair" +, +"Maire" +, +"Maisey" +, +"Maisie" +, +"Maitilde" +, +"Mala" +, +"Malanie" +, +"Malena" +, +"Malia" +, +"Malina" +, +"Malinda" +, +"Malinde" +, +"Malissa" +, +"Malissia" +, +"Mallissa" +, +"Mallorie" +, +"Mallory" +, +"Malorie" +, +"Malory" +, +"Malva" +, +"Malvina" +, +"Malynda" +, +"Mame" +, +"Mamie" +, +"Manda" +, +"Mandi" +, +"Mandie" +, +"Mandy" +, +"Manon" +, +"Manya" +, +"Mara" +, +"Marabel" +, +"Marcela" +, +"Marcelia" +, +"Marcella" +, +"Marcelle" +, +"Marcellina" +, +"Marcelline" +, +"Marchelle" +, +"Marci" +, +"Marcia" +, +"Marcie" +, +"Marcile" +, +"Marcille" +, +"Marcy" +, +"Mareah" +, +"Maren" +, +"Marena" +, +"Maressa" +, +"Marga" +, +"Margalit" +, +"Margalo" +, +"Margaret" +, +"Margareta" +, +"Margarete" +, +"Margaretha" +, +"Margarethe" +, +"Margaretta" +, +"Margarette" +, +"Margarita" +, +"Margaux" +, +"Marge" +, +"Margeaux" +, +"Margery" +, +"Marget" +, +"Margette" +, +"Margi" +, +"Margie" +, +"Margit" +, +"Margo" +, +"Margot" +, +"Margret" +, +"Marguerite" +, +"Margy" +, +"Mari" +, +"Maria" +, +"Mariam" +, +"Marian" +, +"Mariana" +, +"Mariann" +, +"Marianna" +, +"Marianne" +, +"Maribel" +, +"Maribelle" +, +"Maribeth" +, +"Marice" +, +"Maridel" +, +"Marie" +, +"Marie-Ann" +, +"Marie-Jeanne" +, +"Marieann" +, +"Mariejeanne" +, +"Mariel" +, +"Mariele" +, +"Marielle" +, +"Mariellen" +, +"Marietta" +, +"Mariette" +, +"Marigold" +, +"Marijo" +, +"Marika" +, +"Marilee" +, +"Marilin" +, +"Marillin" +, +"Marilyn" +, +"Marin" +, +"Marina" +, +"Marinna" +, +"Marion" +, +"Mariquilla" +, +"Maris" +, +"Marisa" +, +"Mariska" +, +"Marissa" +, +"Marita" +, +"Maritsa" +, +"Mariya" +, +"Marj" +, +"Marja" +, +"Marje" +, +"Marji" +, +"Marjie" +, +"Marjorie" +, +"Marjory" +, +"Marjy" +, +"Marketa" +, +"Marla" +, +"Marlane" +, +"Marleah" +, +"Marlee" +, +"Marleen" +, +"Marlena" +, +"Marlene" +, +"Marley" +, +"Marlie" +, +"Marline" +, +"Marlo" +, +"Marlyn" +, +"Marna" +, +"Marne" +, +"Marney" +, +"Marni" +, +"Marnia" +, +"Marnie" +, +"Marquita" +, +"Marrilee" +, +"Marris" +, +"Marrissa" +, +"Marsha" +, +"Marsiella" +, +"Marta" +, +"Martelle" +, +"Martguerita" +, +"Martha" +, +"Marthe" +, +"Marthena" +, +"Marti" +, +"Martica" +, +"Martie" +, +"Martina" +, +"Martita" +, +"Marty" +, +"Martynne" +, +"Mary" +, +"Marya" +, +"Maryann" +, +"Maryanna" +, +"Maryanne" +, +"Marybelle" +, +"Marybeth" +, +"Maryellen" +, +"Maryjane" +, +"Maryjo" +, +"Maryl" +, +"Marylee" +, +"Marylin" +, +"Marylinda" +, +"Marylou" +, +"Marylynne" +, +"Maryrose" +, +"Marys" +, +"Marysa" +, +"Masha" +, +"Matelda" +, +"Mathilda" +, +"Mathilde" +, +"Matilda" +, +"Matilde" +, +"Matti" +, +"Mattie" +, +"Matty" +, +"Maud" +, +"Maude" +, +"Maudie" +, +"Maura" +, +"Maure" +, +"Maureen" +, +"Maureene" +, +"Maurene" +, +"Maurine" +, +"Maurise" +, +"Maurita" +, +"Maurizia" +, +"Mavis" +, +"Mavra" +, +"Max" +, +"Maxi" +, +"Maxie" +, +"Maxine" +, +"Maxy" +, +"May" +, +"Maybelle" +, +"Maye" +, +"Mead" +, +"Meade" +, +"Meagan" +, +"Meaghan" +, +"Meara" +, +"Mechelle" +, +"Meg" +, +"Megan" +, +"Megen" +, +"Meggi" +, +"Meggie" +, +"Meggy" +, +"Meghan" +, +"Meghann" +, +"Mehetabel" +, +"Mei" +, +"Mel" +, +"Mela" +, +"Melamie" +, +"Melania" +, +"Melanie" +, +"Melantha" +, +"Melany" +, +"Melba" +, +"Melesa" +, +"Melessa" +, +"Melicent" +, +"Melina" +, +"Melinda" +, +"Melinde" +, +"Melisa" +, +"Melisande" +, +"Melisandra" +, +"Melisenda" +, +"Melisent" +, +"Melissa" +, +"Melisse" +, +"Melita" +, +"Melitta" +, +"Mella" +, +"Melli" +, +"Mellicent" +, +"Mellie" +, +"Mellisa" +, +"Mellisent" +, +"Melloney" +, +"Melly" +, +"Melodee" +, +"Melodie" +, +"Melody" +, +"Melonie" +, +"Melony" +, +"Melosa" +, +"Melva" +, +"Mercedes" +, +"Merci" +, +"Mercie" +, +"Mercy" +, +"Meredith" +, +"Meredithe" +, +"Meridel" +, +"Meridith" +, +"Meriel" +, +"Merilee" +, +"Merilyn" +, +"Meris" +, +"Merissa" +, +"Merl" +, +"Merla" +, +"Merle" +, +"Merlina" +, +"Merline" +, +"Merna" +, +"Merola" +, +"Merralee" +, +"Merridie" +, +"Merrie" +, +"Merrielle" +, +"Merrile" +, +"Merrilee" +, +"Merrili" +, +"Merrill" +, +"Merrily" +, +"Merry" +, +"Mersey" +, +"Meryl" +, +"Meta" +, +"Mia" +, +"Micaela" +, +"Michaela" +, +"Michaelina" +, +"Michaeline" +, +"Michaella" +, +"Michal" +, +"Michel" +, +"Michele" +, +"Michelina" +, +"Micheline" +, +"Michell" +, +"Michelle" +, +"Micki" +, +"Mickie" +, +"Micky" +, +"Midge" +, +"Mignon" +, +"Mignonne" +, +"Miguela" +, +"Miguelita" +, +"Mikaela" +, +"Mil" +, +"Mildred" +, +"Mildrid" +, +"Milena" +, +"Milicent" +, +"Milissent" +, +"Milka" +, +"Milli" +, +"Millicent" +, +"Millie" +, +"Millisent" +, +"Milly" +, +"Milzie" +, +"Mimi" +, +"Min" +, +"Mina" +, +"Minda" +, +"Mindy" +, +"Minerva" +, +"Minetta" +, +"Minette" +, +"Minna" +, +"Minnaminnie" +, +"Minne" +, +"Minni" +, +"Minnie" +, +"Minnnie" +, +"Minny" +, +"Minta" +, +"Miof Mela" +, +"Miquela" +, +"Mira" +, +"Mirabel" +, +"Mirabella" +, +"Mirabelle" +, +"Miran" +, +"Miranda" +, +"Mireielle" +, +"Mireille" +, +"Mirella" +, +"Mirelle" +, +"Miriam" +, +"Mirilla" +, +"Mirna" +, +"Misha" +, +"Missie" +, +"Missy" +, +"Misti" +, +"Misty" +, +"Mitzi" +, +"Modesta" +, +"Modestia" +, +"Modestine" +, +"Modesty" +, +"Moina" +, +"Moira" +, +"Moll" +, +"Mollee" +, +"Molli" +, +"Mollie" +, +"Molly" +, +"Mommy" +, +"Mona" +, +"Monah" +, +"Monica" +, +"Monika" +, +"Monique" +, +"Mora" +, +"Moreen" +, +"Morena" +, +"Morgan" +, +"Morgana" +, +"Morganica" +, +"Morganne" +, +"Morgen" +, +"Moria" +, +"Morissa" +, +"Morna" +, +"Moselle" +, +"Moyna" +, +"Moyra" +, +"Mozelle" +, +"Muffin" +, +"Mufi" +, +"Mufinella" +, +"Muire" +, +"Mureil" +, +"Murial" +, +"Muriel" +, +"Murielle" +, +"Myra" +, +"Myrah" +, +"Myranda" +, +"Myriam" +, +"Myrilla" +, +"Myrle" +, +"Myrlene" +, +"Myrna" +, +"Myrta" +, +"Myrtia" +, +"Myrtice" +, +"Myrtie" +, +"Myrtle" +, +"Nada" +, +"Nadean" +, +"Nadeen" +, +"Nadia" +, +"Nadine" +, +"Nadiya" +, +"Nady" +, +"Nadya" +, +"Nalani" +, +"Nan" +, +"Nana" +, +"Nananne" +, +"Nance" +, +"Nancee" +, +"Nancey" +, +"Nanci" +, +"Nancie" +, +"Nancy" +, +"Nanete" +, +"Nanette" +, +"Nani" +, +"Nanice" +, +"Nanine" +, +"Nannette" +, +"Nanni" +, +"Nannie" +, +"Nanny" +, +"Nanon" +, +"Naoma" +, +"Naomi" +, +"Nara" +, +"Nari" +, +"Nariko" +, +"Nat" +, +"Nata" +, +"Natala" +, +"Natalee" +, +"Natalie" +, +"Natalina" +, +"Nataline" +, +"Natalya" +, +"Natasha" +, +"Natassia" +, +"Nathalia" +, +"Nathalie" +, +"Natividad" +, +"Natka" +, +"Natty" +, +"Neala" +, +"Neda" +, +"Nedda" +, +"Nedi" +, +"Neely" +, +"Neila" +, +"Neile" +, +"Neilla" +, +"Neille" +, +"Nelia" +, +"Nelie" +, +"Nell" +, +"Nelle" +, +"Nelli" +, +"Nellie" +, +"Nelly" +, +"Nerissa" +, +"Nerita" +, +"Nert" +, +"Nerta" +, +"Nerte" +, +"Nerti" +, +"Nertie" +, +"Nerty" +, +"Nessa" +, +"Nessi" +, +"Nessie" +, +"Nessy" +, +"Nesta" +, +"Netta" +, +"Netti" +, +"Nettie" +, +"Nettle" +, +"Netty" +, +"Nevsa" +, +"Neysa" +, +"Nichol" +, +"Nichole" +, +"Nicholle" +, +"Nicki" +, +"Nickie" +, +"Nicky" +, +"Nicol" +, +"Nicola" +, +"Nicole" +, +"Nicolea" +, +"Nicolette" +, +"Nicoli" +, +"Nicolina" +, +"Nicoline" +, +"Nicolle" +, +"Nikaniki" +, +"Nike" +, +"Niki" +, +"Nikki" +, +"Nikkie" +, +"Nikoletta" +, +"Nikolia" +, +"Nina" +, +"Ninetta" +, +"Ninette" +, +"Ninnetta" +, +"Ninnette" +, +"Ninon" +, +"Nissa" +, +"Nisse" +, +"Nissie" +, +"Nissy" +, +"Nita" +, +"Nixie" +, +"Noami" +, +"Noel" +, +"Noelani" +, +"Noell" +, +"Noella" +, +"Noelle" +, +"Noellyn" +, +"Noelyn" +, +"Noemi" +, +"Nola" +, +"Nolana" +, +"Nolie" +, +"Nollie" +, +"Nomi" +, +"Nona" +, +"Nonah" +, +"Noni" +, +"Nonie" +, +"Nonna" +, +"Nonnah" +, +"Nora" +, +"Norah" +, +"Norean" +, +"Noreen" +, +"Norene" +, +"Norina" +, +"Norine" +, +"Norma" +, +"Norri" +, +"Norrie" +, +"Norry" +, +"Novelia" +, +"Nydia" +, +"Nyssa" +, +"Octavia" +, +"Odele" +, +"Odelia" +, +"Odelinda" +, +"Odella" +, +"Odelle" +, +"Odessa" +, +"Odetta" +, +"Odette" +, +"Odilia" +, +"Odille" +, +"Ofelia" +, +"Ofella" +, +"Ofilia" +, +"Ola" +, +"Olenka" +, +"Olga" +, +"Olia" +, +"Olimpia" +, +"Olive" +, +"Olivette" +, +"Olivia" +, +"Olivie" +, +"Oliy" +, +"Ollie" +, +"Olly" +, +"Olva" +, +"Olwen" +, +"Olympe" +, +"Olympia" +, +"Olympie" +, +"Ondrea" +, +"Oneida" +, +"Onida" +, +"Oona" +, +"Opal" +, +"Opalina" +, +"Opaline" +, +"Ophelia" +, +"Ophelie" +, +"Ora" +, +"Oralee" +, +"Oralia" +, +"Oralie" +, +"Oralla" +, +"Oralle" +, +"Orel" +, +"Orelee" +, +"Orelia" +, +"Orelie" +, +"Orella" +, +"Orelle" +, +"Oriana" +, +"Orly" +, +"Orsa" +, +"Orsola" +, +"Ortensia" +, +"Otha" +, +"Othelia" +, +"Othella" +, +"Othilia" +, +"Othilie" +, +"Ottilie" +, +"Page" +, +"Paige" +, +"Paloma" +, +"Pam" +, +"Pamela" +, +"Pamelina" +, +"Pamella" +, +"Pammi" +, +"Pammie" +, +"Pammy" +, +"Pandora" +, +"Pansie" +, +"Pansy" +, +"Paola" +, +"Paolina" +, +"Papagena" +, +"Pat" +, +"Patience" +, +"Patrica" +, +"Patrice" +, +"Patricia" +, +"Patrizia" +, +"Patsy" +, +"Patti" +, +"Pattie" +, +"Patty" +, +"Paula" +, +"Paule" +, +"Pauletta" +, +"Paulette" +, +"Pauli" +, +"Paulie" +, +"Paulina" +, +"Pauline" +, +"Paulita" +, +"Pauly" +, +"Pavia" +, +"Pavla" +, +"Pearl" +, +"Pearla" +, +"Pearle" +, +"Pearline" +, +"Peg" +, +"Pegeen" +, +"Peggi" +, +"Peggie" +, +"Peggy" +, +"Pen" +, +"Penelopa" +, +"Penelope" +, +"Penni" +, +"Pennie" +, +"Penny" +, +"Pepi" +, +"Pepita" +, +"Peri" +, +"Peria" +, +"Perl" +, +"Perla" +, +"Perle" +, +"Perri" +, +"Perrine" +, +"Perry" +, +"Persis" +, +"Pet" +, +"Peta" +, +"Petra" +, +"Petrina" +, +"Petronella" +, +"Petronia" +, +"Petronilla" +, +"Petronille" +, +"Petunia" +, +"Phaedra" +, +"Phaidra" +, +"Phebe" +, +"Phedra" +, +"Phelia" +, +"Phil" +, +"Philipa" +, +"Philippa" +, +"Philippe" +, +"Philippine" +, +"Philis" +, +"Phillida" +, +"Phillie" +, +"Phillis" +, +"Philly" +, +"Philomena" +, +"Phoebe" +, +"Phylis" +, +"Phyllida" +, +"Phyllis" +, +"Phyllys" +, +"Phylys" +, +"Pia" +, +"Pier" +, +"Pierette" +, +"Pierrette" +, +"Pietra" +, +"Piper" +, +"Pippa" +, +"Pippy" +, +"Polly" +, +"Pollyanna" +, +"Pooh" +, +"Poppy" +, +"Portia" +, +"Pris" +, +"Prisca" +, +"Priscella" +, +"Priscilla" +, +"Prissie" +, +"Pru" +, +"Prudence" +, +"Prudi" +, +"Prudy" +, +"Prue" +, +"Queenie" +, +"Quentin" +, +"Querida" +, +"Quinn" +, +"Quinta" +, +"Quintana" +, +"Quintilla" +, +"Quintina" +, +"Rachael" +, +"Rachel" +, +"Rachele" +, +"Rachelle" +, +"Rae" +, +"Raeann" +, +"Raf" +, +"Rafa" +, +"Rafaela" +, +"Rafaelia" +, +"Rafaelita" +, +"Rahal" +, +"Rahel" +, +"Raina" +, +"Raine" +, +"Rakel" +, +"Ralina" +, +"Ramona" +, +"Ramonda" +, +"Rana" +, +"Randa" +, +"Randee" +, +"Randene" +, +"Randi" +, +"Randie" +, +"Randy" +, +"Ranee" +, +"Rani" +, +"Rania" +, +"Ranice" +, +"Ranique" +, +"Ranna" +, +"Raphaela" +, +"Raquel" +, +"Raquela" +, +"Rasia" +, +"Rasla" +, +"Raven" +, +"Ray" +, +"Raychel" +, +"Raye" +, +"Rayna" +, +"Raynell" +, +"Rayshell" +, +"Rea" +, +"Reba" +, +"Rebbecca" +, +"Rebe" +, +"Rebeca" +, +"Rebecca" +, +"Rebecka" +, +"Rebeka" +, +"Rebekah" +, +"Rebekkah" +, +"Ree" +, +"Reeba" +, +"Reena" +, +"Reeta" +, +"Reeva" +, +"Regan" +, +"Reggi" +, +"Reggie" +, +"Regina" +, +"Regine" +, +"Reiko" +, +"Reina" +, +"Reine" +, +"Remy" +, +"Rena" +, +"Renae" +, +"Renata" +, +"Renate" +, +"Rene" +, +"Renee" +, +"Renell" +, +"Renelle" +, +"Renie" +, +"Rennie" +, +"Reta" +, +"Retha" +, +"Revkah" +, +"Rey" +, +"Reyna" +, +"Rhea" +, +"Rheba" +, +"Rheta" +, +"Rhetta" +, +"Rhiamon" +, +"Rhianna" +, +"Rhianon" +, +"Rhoda" +, +"Rhodia" +, +"Rhodie" +, +"Rhody" +, +"Rhona" +, +"Rhonda" +, +"Riane" +, +"Riannon" +, +"Rianon" +, +"Rica" +, +"Ricca" +, +"Rici" +, +"Ricki" +, +"Rickie" +, +"Ricky" +, +"Riki" +, +"Rikki" +, +"Rina" +, +"Risa" +, +"Rita" +, +"Riva" +, +"Rivalee" +, +"Rivi" +, +"Rivkah" +, +"Rivy" +, +"Roana" +, +"Roanna" +, +"Roanne" +, +"Robbi" +, +"Robbie" +, +"Robbin" +, +"Robby" +, +"Robbyn" +, +"Robena" +, +"Robenia" +, +"Roberta" +, +"Robin" +, +"Robina" +, +"Robinet" +, +"Robinett" +, +"Robinetta" +, +"Robinette" +, +"Robinia" +, +"Roby" +, +"Robyn" +, +"Roch" +, +"Rochell" +, +"Rochella" +, +"Rochelle" +, +"Rochette" +, +"Roda" +, +"Rodi" +, +"Rodie" +, +"Rodina" +, +"Rois" +, +"Romola" +, +"Romona" +, +"Romonda" +, +"Romy" +, +"Rona" +, +"Ronalda" +, +"Ronda" +, +"Ronica" +, +"Ronna" +, +"Ronni" +, +"Ronnica" +, +"Ronnie" +, +"Ronny" +, +"Roobbie" +, +"Rora" +, +"Rori" +, +"Rorie" +, +"Rory" +, +"Ros" +, +"Rosa" +, +"Rosabel" +, +"Rosabella" +, +"Rosabelle" +, +"Rosaleen" +, +"Rosalia" +, +"Rosalie" +, +"Rosalind" +, +"Rosalinda" +, +"Rosalinde" +, +"Rosaline" +, +"Rosalyn" +, +"Rosalynd" +, +"Rosamond" +, +"Rosamund" +, +"Rosana" +, +"Rosanna" +, +"Rosanne" +, +"Rose" +, +"Roseann" +, +"Roseanna" +, +"Roseanne" +, +"Roselia" +, +"Roselin" +, +"Roseline" +, +"Rosella" +, +"Roselle" +, +"Rosemaria" +, +"Rosemarie" +, +"Rosemary" +, +"Rosemonde" +, +"Rosene" +, +"Rosetta" +, +"Rosette" +, +"Roshelle" +, +"Rosie" +, +"Rosina" +, +"Rosita" +, +"Roslyn" +, +"Rosmunda" +, +"Rosy" +, +"Row" +, +"Rowe" +, +"Rowena" +, +"Roxana" +, +"Roxane" +, +"Roxanna" +, +"Roxanne" +, +"Roxi" +, +"Roxie" +, +"Roxine" +, +"Roxy" +, +"Roz" +, +"Rozalie" +, +"Rozalin" +, +"Rozamond" +, +"Rozanna" +, +"Rozanne" +, +"Roze" +, +"Rozele" +, +"Rozella" +, +"Rozelle" +, +"Rozina" +, +"Rubetta" +, +"Rubi" +, +"Rubia" +, +"Rubie" +, +"Rubina" +, +"Ruby" +, +"Ruperta" +, +"Ruth" +, +"Ruthann" +, +"Ruthanne" +, +"Ruthe" +, +"Ruthi" +, +"Ruthie" +, +"Ruthy" +, +"Ryann" +, +"Rycca" +, +"Saba" +, +"Sabina" +, +"Sabine" +, +"Sabra" +, +"Sabrina" +, +"Sacha" +, +"Sada" +, +"Sadella" +, +"Sadie" +, +"Sadye" +, +"Saidee" +, +"Sal" +, +"Salaidh" +, +"Sallee" +, +"Salli" +, +"Sallie" +, +"Sally" +, +"Sallyann" +, +"Sallyanne" +, +"Saloma" +, +"Salome" +, +"Salomi" +, +"Sam" +, +"Samantha" +, +"Samara" +, +"Samaria" +, +"Sammy" +, +"Sande" +, +"Sandi" +, +"Sandie" +, +"Sandra" +, +"Sandy" +, +"Sandye" +, +"Sapphira" +, +"Sapphire" +, +"Sara" +, +"Sara-Ann" +, +"Saraann" +, +"Sarah" +, +"Sarajane" +, +"Saree" +, +"Sarena" +, +"Sarene" +, +"Sarette" +, +"Sari" +, +"Sarina" +, +"Sarine" +, +"Sarita" +, +"Sascha" +, +"Sasha" +, +"Sashenka" +, +"Saudra" +, +"Saundra" +, +"Savina" +, +"Sayre" +, +"Scarlet" +, +"Scarlett" +, +"Sean" +, +"Seana" +, +"Seka" +, +"Sela" +, +"Selena" +, +"Selene" +, +"Selestina" +, +"Selia" +, +"Selie" +, +"Selina" +, +"Selinda" +, +"Seline" +, +"Sella" +, +"Selle" +, +"Selma" +, +"Sena" +, +"Sephira" +, +"Serena" +, +"Serene" +, +"Shae" +, +"Shaina" +, +"Shaine" +, +"Shalna" +, +"Shalne" +, +"Shana" +, +"Shanda" +, +"Shandee" +, +"Shandeigh" +, +"Shandie" +, +"Shandra" +, +"Shandy" +, +"Shane" +, +"Shani" +, +"Shanie" +, +"Shanna" +, +"Shannah" +, +"Shannen" +, +"Shannon" +, +"Shanon" +, +"Shanta" +, +"Shantee" +, +"Shara" +, +"Sharai" +, +"Shari" +, +"Sharia" +, +"Sharity" +, +"Sharl" +, +"Sharla" +, +"Sharleen" +, +"Sharlene" +, +"Sharline" +, +"Sharon" +, +"Sharona" +, +"Sharron" +, +"Sharyl" +, +"Shaun" +, +"Shauna" +, +"Shawn" +, +"Shawna" +, +"Shawnee" +, +"Shay" +, +"Shayla" +, +"Shaylah" +, +"Shaylyn" +, +"Shaylynn" +, +"Shayna" +, +"Shayne" +, +"Shea" +, +"Sheba" +, +"Sheela" +, +"Sheelagh" +, +"Sheelah" +, +"Sheena" +, +"Sheeree" +, +"Sheila" +, +"Sheila-Kathryn" +, +"Sheilah" +, +"Shel" +, +"Shela" +, +"Shelagh" +, +"Shelba" +, +"Shelbi" +, +"Shelby" +, +"Shelia" +, +"Shell" +, +"Shelley" +, +"Shelli" +, +"Shellie" +, +"Shelly" +, +"Shena" +, +"Sher" +, +"Sheree" +, +"Sheri" +, +"Sherie" +, +"Sherill" +, +"Sherilyn" +, +"Sherline" +, +"Sherri" +, +"Sherrie" +, +"Sherry" +, +"Sherye" +, +"Sheryl" +, +"Shina" +, +"Shir" +, +"Shirl" +, +"Shirlee" +, +"Shirleen" +, +"Shirlene" +, +"Shirley" +, +"Shirline" +, +"Shoshana" +, +"Shoshanna" +, +"Siana" +, +"Sianna" +, +"Sib" +, +"Sibbie" +, +"Sibby" +, +"Sibeal" +, +"Sibel" +, +"Sibella" +, +"Sibelle" +, +"Sibilla" +, +"Sibley" +, +"Sibyl" +, +"Sibylla" +, +"Sibylle" +, +"Sidoney" +, +"Sidonia" +, +"Sidonnie" +, +"Sigrid" +, +"Sile" +, +"Sileas" +, +"Silva" +, +"Silvana" +, +"Silvia" +, +"Silvie" +, +"Simona" +, +"Simone" +, +"Simonette" +, +"Simonne" +, +"Sindee" +, +"Siobhan" +, +"Sioux" +, +"Siouxie" +, +"Sisely" +, +"Sisile" +, +"Sissie" +, +"Sissy" +, +"Siusan" +, +"Sofia" +, +"Sofie" +, +"Sondra" +, +"Sonia" +, +"Sonja" +, +"Sonni" +, +"Sonnie" +, +"Sonnnie" +, +"Sonny" +, +"Sonya" +, +"Sophey" +, +"Sophi" +, +"Sophia" +, +"Sophie" +, +"Sophronia" +, +"Sorcha" +, +"Sosanna" +, +"Stace" +, +"Stacee" +, +"Stacey" +, +"Staci" +, +"Stacia" +, +"Stacie" +, +"Stacy" +, +"Stafani" +, +"Star" +, +"Starla" +, +"Starlene" +, +"Starlin" +, +"Starr" +, +"Stefa" +, +"Stefania" +, +"Stefanie" +, +"Steffane" +, +"Steffi" +, +"Steffie" +, +"Stella" +, +"Stepha" +, +"Stephana" +, +"Stephani" +, +"Stephanie" +, +"Stephannie" +, +"Stephenie" +, +"Stephi" +, +"Stephie" +, +"Stephine" +, +"Stesha" +, +"Stevana" +, +"Stevena" +, +"Stoddard" +, +"Storm" +, +"Stormi" +, +"Stormie" +, +"Stormy" +, +"Sue" +, +"Suellen" +, +"Sukey" +, +"Suki" +, +"Sula" +, +"Sunny" +, +"Sunshine" +, +"Susan" +, +"Susana" +, +"Susanetta" +, +"Susann" +, +"Susanna" +, +"Susannah" +, +"Susanne" +, +"Susette" +, +"Susi" +, +"Susie" +, +"Susy" +, +"Suzann" +, +"Suzanna" +, +"Suzanne" +, +"Suzette" +, +"Suzi" +, +"Suzie" +, +"Suzy" +, +"Sybil" +, +"Sybila" +, +"Sybilla" +, +"Sybille" +, +"Sybyl" +, +"Sydel" +, +"Sydelle" +, +"Sydney" +, +"Sylvia" +, +"Tabatha" +, +"Tabbatha" +, +"Tabbi" +, +"Tabbie" +, +"Tabbitha" +, +"Tabby" +, +"Tabina" +, +"Tabitha" +, +"Taffy" +, +"Talia" +, +"Tallia" +, +"Tallie" +, +"Tallou" +, +"Tallulah" +, +"Tally" +, +"Talya" +, +"Talyah" +, +"Tamar" +, +"Tamara" +, +"Tamarah" +, +"Tamarra" +, +"Tamera" +, +"Tami" +, +"Tamiko" +, +"Tamma" +, +"Tammara" +, +"Tammi" +, +"Tammie" +, +"Tammy" +, +"Tamqrah" +, +"Tamra" +, +"Tana" +, +"Tandi" +, +"Tandie" +, +"Tandy" +, +"Tanhya" +, +"Tani" +, +"Tania" +, +"Tanitansy" +, +"Tansy" +, +"Tanya" +, +"Tara" +, +"Tarah" +, +"Tarra" +, +"Tarrah" +, +"Taryn" +, +"Tasha" +, +"Tasia" +, +"Tate" +, +"Tatiana" +, +"Tatiania" +, +"Tatum" +, +"Tawnya" +, +"Tawsha" +, +"Ted" +, +"Tedda" +, +"Teddi" +, +"Teddie" +, +"Teddy" +, +"Tedi" +, +"Tedra" +, +"Teena" +, +"TEirtza" +, +"Teodora" +, +"Tera" +, +"Teresa" +, +"Terese" +, +"Teresina" +, +"Teresita" +, +"Teressa" +, +"Teri" +, +"Teriann" +, +"Terra" +, +"Terri" +, +"Terrie" +, +"Terrijo" +, +"Terry" +, +"Terrye" +, +"Tersina" +, +"Terza" +, +"Tess" +, +"Tessa" +, +"Tessi" +, +"Tessie" +, +"Tessy" +, +"Thalia" +, +"Thea" +, +"Theadora" +, +"Theda" +, +"Thekla" +, +"Thelma" +, +"Theo" +, +"Theodora" +, +"Theodosia" +, +"Theresa" +, +"Therese" +, +"Theresina" +, +"Theresita" +, +"Theressa" +, +"Therine" +, +"Thia" +, +"Thomasa" +, +"Thomasin" +, +"Thomasina" +, +"Thomasine" +, +"Tiena" +, +"Tierney" +, +"Tiertza" +, +"Tiff" +, +"Tiffani" +, +"Tiffanie" +, +"Tiffany" +, +"Tiffi" +, +"Tiffie" +, +"Tiffy" +, +"Tilda" +, +"Tildi" +, +"Tildie" +, +"Tildy" +, +"Tillie" +, +"Tilly" +, +"Tim" +, +"Timi" +, +"Timmi" +, +"Timmie" +, +"Timmy" +, +"Timothea" +, +"Tina" +, +"Tine" +, +"Tiphani" +, +"Tiphanie" +, +"Tiphany" +, +"Tish" +, +"Tisha" +, +"Tobe" +, +"Tobey" +, +"Tobi" +, +"Toby" +, +"Tobye" +, +"Toinette" +, +"Toma" +, +"Tomasina" +, +"Tomasine" +, +"Tomi" +, +"Tommi" +, +"Tommie" +, +"Tommy" +, +"Toni" +, +"Tonia" +, +"Tonie" +, +"Tony" +, +"Tonya" +, +"Tonye" +, +"Tootsie" +, +"Torey" +, +"Tori" +, +"Torie" +, +"Torrie" +, +"Tory" +, +"Tova" +, +"Tove" +, +"Tracee" +, +"Tracey" +, +"Traci" +, +"Tracie" +, +"Tracy" +, +"Trenna" +, +"Tresa" +, +"Trescha" +, +"Tressa" +, +"Tricia" +, +"Trina" +, +"Trish" +, +"Trisha" +, +"Trista" +, +"Trix" +, +"Trixi" +, +"Trixie" +, +"Trixy" +, +"Truda" +, +"Trude" +, +"Trudey" +, +"Trudi" +, +"Trudie" +, +"Trudy" +, +"Trula" +, +"Tuesday" +, +"Twila" +, +"Twyla" +, +"Tybi" +, +"Tybie" +, +"Tyne" +, +"Ula" +, +"Ulla" +, +"Ulrica" +, +"Ulrika" +, +"Ulrikaumeko" +, +"Ulrike" +, +"Umeko" +, +"Una" +, +"Ursa" +, +"Ursala" +, +"Ursola" +, +"Ursula" +, +"Ursulina" +, +"Ursuline" +, +"Uta" +, +"Val" +, +"Valaree" +, +"Valaria" +, +"Vale" +, +"Valeda" +, +"Valencia" +, +"Valene" +, +"Valenka" +, +"Valentia" +, +"Valentina" +, +"Valentine" +, +"Valera" +, +"Valeria" +, +"Valerie" +, +"Valery" +, +"Valerye" +, +"Valida" +, +"Valina" +, +"Valli" +, +"Vallie" +, +"Vally" +, +"Valma" +, +"Valry" +, +"Van" +, +"Vanda" +, +"Vanessa" +, +"Vania" +, +"Vanna" +, +"Vanni" +, +"Vannie" +, +"Vanny" +, +"Vanya" +, +"Veda" +, +"Velma" +, +"Velvet" +, +"Venita" +, +"Venus" +, +"Vera" +, +"Veradis" +, +"Vere" +, +"Verena" +, +"Verene" +, +"Veriee" +, +"Verile" +, +"Verina" +, +"Verine" +, +"Verla" +, +"Verna" +, +"Vernice" +, +"Veronica" +, +"Veronika" +, +"Veronike" +, +"Veronique" +, +"Vevay" +, +"Vi" +, +"Vicki" +, +"Vickie" +, +"Vicky" +, +"Victoria" +, +"Vida" +, +"Viki" +, +"Vikki" +, +"Vikky" +, +"Vilhelmina" +, +"Vilma" +, +"Vin" +, +"Vina" +, +"Vinita" +, +"Vinni" +, +"Vinnie" +, +"Vinny" +, +"Viola" +, +"Violante" +, +"Viole" +, +"Violet" +, +"Violetta" +, +"Violette" +, +"Virgie" +, +"Virgina" +, +"Virginia" +, +"Virginie" +, +"Vita" +, +"Vitia" +, +"Vitoria" +, +"Vittoria" +, +"Viv" +, +"Viva" +, +"Vivi" +, +"Vivia" +, +"Vivian" +, +"Viviana" +, +"Vivianna" +, +"Vivianne" +, +"Vivie" +, +"Vivien" +, +"Viviene" +, +"Vivienne" +, +"Viviyan" +, +"Vivyan" +, +"Vivyanne" +, +"Vonni" +, +"Vonnie" +, +"Vonny" +, +"Vyky" +, +"Wallie" +, +"Wallis" +, +"Walliw" +, +"Wally" +, +"Waly" +, +"Wanda" +, +"Wandie" +, +"Wandis" +, +"Waneta" +, +"Wanids" +, +"Wenda" +, +"Wendeline" +, +"Wendi" +, +"Wendie" +, +"Wendy" +, +"Wendye" +, +"Wenona" +, +"Wenonah" +, +"Whitney" +, +"Wileen" +, +"Wilhelmina" +, +"Wilhelmine" +, +"Wilie" +, +"Willa" +, +"Willabella" +, +"Willamina" +, +"Willetta" +, +"Willette" +, +"Willi" +, +"Willie" +, +"Willow" +, +"Willy" +, +"Willyt" +, +"Wilma" +, +"Wilmette" +, +"Wilona" +, +"Wilone" +, +"Wilow" +, +"Windy" +, +"Wini" +, +"Winifred" +, +"Winna" +, +"Winnah" +, +"Winne" +, +"Winni" +, +"Winnie" +, +"Winnifred" +, +"Winny" +, +"Winona" +, +"Winonah" +, +"Wren" +, +"Wrennie" +, +"Wylma" +, +"Wynn" +, +"Wynne" +, +"Wynnie" +, +"Wynny" +, +"Xaviera" +, +"Xena" +, +"Xenia" +, +"Xylia" +, +"Xylina" +, +"Yalonda" +, +"Yasmeen" +, +"Yasmin" +, +"Yelena" +, +"Yetta" +, +"Yettie" +, +"Yetty" +, +"Yevette" +, +"Ynes" +, +"Ynez" +, +"Yoko" +, +"Yolanda" +, +"Yolande" +, +"Yolane" +, +"Yolanthe" +, +"Yoshi" +, +"Yoshiko" +, +"Yovonnda" +, +"Ysabel" +, +"Yvette" +, +"Yvonne" +, +"Zabrina" +, +"Zahara" +, +"Zandra" +, +"Zaneta" +, +"Zara" +, +"Zarah" +, +"Zaria" +, +"Zarla" +, +"Zea" +, +"Zelda" +, +"Zelma" +, +"Zena" +, +"Zenia" +, +"Zia" +, +"Zilvia" +, +"Zita" +, +"Zitella" +, +"Zoe" +, +"Zola" +, +"Zonda" +, +"Zondra" +, +"Zonnya" +, +"Zora" +, +"Zorah" +, +"Zorana" +, +"Zorina" +, +"Zorine" +, +"Zsa Zsa" +, +"Zsazsa" +, +"Zulema" +, +"Zuzana" +] diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameCell.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameCell.swift new file mode 100644 index 00000000..d388819e --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameCell.swift @@ -0,0 +1,29 @@ +import UIKit +import Utilities + +final class NameCell: LabelCell { + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + private func commonInit() { + label.textAlignment = .left + label.font = .preferredFont(forTextStyle: .body) + label.adjustsFontForContentSizeCategory = true + } + + override func prepareForReuse() { + super.prepareForReuse() + label.text = nil + } + + func set(name: String) { + label.text = name + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameSectionHeaderView.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameSectionHeaderView.swift new file mode 100644 index 00000000..36f7bb6c --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NameSectionHeaderView.swift @@ -0,0 +1,54 @@ +import UIKit +import Utilities + +final class NameSectionHeaderView: LabelSupplementaryView { + private var headerPressedHandler: (() -> Void)? + + private lazy var closeIcon = UIImageView(image: .init(systemName: "x.circle")) + + private lazy var gestureRecognizer = UITapGestureRecognizer( + target: self, + action: #selector(headerPressed) + ) + + override init(frame: CGRect) { + super.init(frame: frame) + commonInit() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + commonInit() + } + + private func commonInit() { + addGestureRecognizer(gestureRecognizer) + backgroundColor = .systemGray6 + label.font = .preferredFont(forTextStyle: .title2) + addSubview(closeIcon) + closeIcon.translatesAutoresizingMaskIntoConstraints = false + closeIcon.tintColor = .black + NSLayoutConstraint.activate([ + closeIcon.centerYAnchor.constraint(equalTo: layoutMarginsGuide.centerYAnchor), + closeIcon.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor) + ]) + } + + @objc private func headerPressed() { + headerPressedHandler?() + } + + func set( + title: String, + headerPressedHandler: @escaping () -> Void + ) { + self.label.text = title + self.headerPressedHandler = headerPressedHandler + } + + override func prepareForReuse() { + super.prepareForReuse() + label.text = nil + headerPressedHandler = nil + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+NamesSectionNavigation.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+NamesSectionNavigation.swift new file mode 100644 index 00000000..cdea85f1 --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+NamesSectionNavigation.swift @@ -0,0 +1,13 @@ +import UIKit + +extension NamesCoordinator: NamesSectionNavigation { + func show(name: String) { + let alertController = UIAlertController( + title: "Someone being choosed", + message: "Amazing \(name) is nominated!", + preferredStyle: .alert + ) + alertController.addAction(UIAlertAction(title: "OK", style: .default)) + navigationController.present(alertController, animated: true) + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+Presentable.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+Presentable.swift new file mode 100644 index 00000000..3d08989f --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator+Presentable.swift @@ -0,0 +1,14 @@ +import UIKit +import Utilities + +extension NamesCoordinator: Presentable { + private func makeViewController() -> UIViewController { + let viewModel = NamesViewModel(navigation: self) + return NamesViewController(viewModel: viewModel) + } + + @discardableResult + public func present(segue: NavigationSegue) -> NavigationSegue.RewindAction { + segue.invoke(with: makeViewController()) + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator.swift new file mode 100644 index 00000000..1cb03d6f --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesCoordinator.swift @@ -0,0 +1,9 @@ +import UIKit + +public struct NamesCoordinator { + unowned let navigationController: UINavigationController + + public init(navigationController: UINavigationController) { + self.navigationController = navigationController + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift new file mode 100644 index 00000000..62790869 --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift @@ -0,0 +1,76 @@ +import SectionKit +import UIKit + +final class NamesSectionController: ListCompositionalLayoutSectionController< + NamesSectionViewModelType, + String +> { + override func layoutSection( + layoutEnvironment: NSCollectionLayoutEnvironment + ) -> NSCollectionLayoutSection { + let layoutSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1), + heightDimension: .estimated(50) + ) + + let item = NSCollectionLayoutItem(layoutSize: layoutSize) + let layout = NSCollectionLayoutSection( + group: .vertical( + layoutSize: layoutSize, + subitem: item, + count: 1 + ) + ) + let header = NSCollectionLayoutBoundarySupplementaryItem( + layoutSize: .init( + widthDimension: .fractionalWidth(1), + heightDimension: .estimated(30) + ), + elementKind: UICollectionView.elementKindSectionHeader, + alignment: .top + ) + header.pinToVisibleBounds = true + + // Hide the section header if it's collapsed + if !model.isCollapsed { + layout.boundarySupplementaryItems = [header] + } else { + layout.boundarySupplementaryItems = [] + } + return layout + } + + override func items(for model: NamesSectionViewModelType) -> [String] { + model.isCollapsed ? [] : model.names + } + + override func cellForItem( + at indexPath: SectionIndexPath, + in context: CollectionViewContext + ) -> UICollectionViewCell { + let cell: NameCell = context.dequeueReusableCell(for: indexPath) + cell.set(name: items[indexPath]) + return cell + } + + override func didSelectItem(at indexPath: SectionIndexPath, in context: CollectionViewContext) { + model.select(name: items[indexPath]) + context.collectionView.deselectItem(at: indexPath.indexInCollectionView, animated: true) + } + + // MARK: - Header + + override func headerView( + at indexPath: SectionIndexPath, + in context: any CollectionViewContext + ) -> UICollectionReusableView { + let header: NameSectionHeaderView = context.dequeueReusableHeaderView(for: indexPath) + header.set(title: model.sectionId) { [weak self] in + guard let self else { return } + self.model.pressCollapse() + // Reload the items + self.items = items(for: self.model) + } + return header + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionViewModel.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionViewModel.swift new file mode 100644 index 00000000..6282844b --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionViewModel.swift @@ -0,0 +1,46 @@ +import Foundation + +typealias NamesSectionViewModelType = NamesSectionViewModelInputs & NamesSectionViewModelOutputs + +protocol NamesSectionViewModelInputs { + func select(name: String) + func pressCollapse() +} + +protocol NamesSectionViewModelOutputs { + var sectionId: String { get } + var sectionTitle: String { get } + var names: [String] { get } + var isCollapsed: Bool { get } +} + +protocol NamesSectionNavigation { + func show(name: String) +} + +final class NamesSectionViewModel: NamesSectionViewModelType { + private let navigation: NamesSectionNavigation + let sectionId: String + let sectionTitle: String + let names: [String] + private(set) var isCollapsed = false + + init( + sectionTitle: String, + names: [String], + navigation: NamesSectionNavigation + ) { + self.sectionId = sectionTitle + self.sectionTitle = sectionTitle + self.names = names + self.navigation = navigation + } + + func select(name: String) { + navigation.show(name: name) + } + + func pressCollapse() { + isCollapsed.toggle() + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewController.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewController.swift new file mode 100644 index 00000000..8331b7a0 --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewController.swift @@ -0,0 +1,51 @@ +import UIKit +import SectionKit + +final class NamesViewController: UIViewController { + private let viewModel: NamesViewModelType + + private lazy var collectionView: UICollectionView = { + let layout = SectionKitCompositionalLayout() + let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) + collectionView.backgroundColor = .systemBackground + collectionView.alwaysBounceVertical = true + return collectionView + }() + + private lazy var collectionViewAdapter = ListCollectionViewAdapter( + collectionView: collectionView, + dataSource: self + ) + + init(viewModel: NamesViewModelType) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required internal init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func loadView() { + view = collectionView + } + + override func viewDidLoad() { + super.viewDidLoad() + title = viewModel.title + collectionViewAdapter.invalidateDataSource() + } +} + +extension NamesViewController: ListCollectionViewAdapterDataSource { + internal func sections(for adapter: CollectionViewAdapter) -> [Section] { + viewModel.sections.map { + Section( + id: $0.sectionId, + model: $0, + controller: NamesSectionController(model: $0) + ) + } + } +} diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewModel.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewModel.swift new file mode 100644 index 00000000..91841eaa --- /dev/null +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesViewModel.swift @@ -0,0 +1,48 @@ +import Foundation + +typealias NamesViewModelType = NamesViewModelInputs & NamesViewModelOutputs + +protocol NamesViewModelInputs { } + +internal protocol NamesViewModelOutputs { + var title: String { get } + var sections: [NamesSectionViewModelType] { get } +} + +struct NamesViewModel: NamesViewModelType { + let title = "Names" + let sections: [NamesSectionViewModelType] + + init(navigation: NamesSectionNavigation) { + let namesDictionary: [String: [String]] + + if let url = Bundle.main.url( + forResource: "first-names", + withExtension: "json" + ) { + do { + let data = try Data(contentsOf: url) + let decoder = JSONDecoder() + let firstnames = try decoder.decode([String].self, from: data) + namesDictionary = Dictionary.init(grouping: firstnames, by: { firstname in + firstname.first.map { String($0) } ?? "" + }) + } catch { + print("error:\(error)") + namesDictionary = [:] + } + } else { + namesDictionary = [:] + } + self.sections = namesDictionary.keys + .sorted() + .compactMap { key -> NamesSectionViewModel? in + guard let names = namesDictionary[key] else { return nil } + return NamesSectionViewModel( + sectionTitle: key, + names: names, + navigation: navigation + ) + } + } +} From 725c14453804661d5627106e9bd93dc0f701a35f Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 3 Apr 2024 15:28:48 +0200 Subject: [PATCH 16/24] Update Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift Co-authored-by: Nataniel martin --- .../ExampleList/ExampleListCoordinator+Presentable.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift b/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift index 8702b4ab..136a4178 100644 --- a/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift +++ b/Example/Examples/Sources/Examples/ExampleList/ExampleListCoordinator+Presentable.swift @@ -39,7 +39,7 @@ extension ExampleListCoordinator: Presentable { ), ExampleViewModel( name: "Names", - description: "An MVVM-C arichitecture with compositional layout example by using a ListCompositionalLayoutCollectionViewAdapter that shows multiple ListCompositionalLayoutSectionController.", + description: "An MVVM-C architecture with compositional layout example by using a ListCompositionalLayoutCollectionViewAdapter that shows multiple ListCompositionalLayoutSectionController.", navigation: ExampleCoordinator( navigationController: navigationController, presentable: NamesCoordinator(navigationController: navigationController) From 5a2e38bd5c09b60163ce2a5a44cdd85b2e02ea24 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 17:40:07 +0200 Subject: [PATCH 17/24] update example --- .../Names/NamesSectionController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift index 62790869..b14881d6 100644 --- a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift @@ -1,13 +1,11 @@ import SectionKit import UIKit -final class NamesSectionController: ListCompositionalLayoutSectionController< +final class NamesSectionController: ListSectionController< NamesSectionViewModelType, String > { - override func layoutSection( - layoutEnvironment: NSCollectionLayoutEnvironment - ) -> NSCollectionLayoutSection { + override var layoutProvider: SectionLayoutProvider? { let layoutSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1), heightDimension: .estimated(50) @@ -37,7 +35,9 @@ final class NamesSectionController: ListCompositionalLayoutSectionController< } else { layout.boundarySupplementaryItems = [] } - return layout + return .compositionalLayout( + .init(layoutSection: { _ in layout }) + ) } override func items(for model: NamesSectionViewModelType) -> [String] { From cd6ee38bec8cebd4c017887bba36d4586fad7fe4 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 10 Apr 2024 17:55:56 +0200 Subject: [PATCH 18/24] fix proj file --- SectionKit.xcodeproj/project.pbxproj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/SectionKit.xcodeproj/project.pbxproj b/SectionKit.xcodeproj/project.pbxproj index 2024c5b8..4052815b 100644 --- a/SectionKit.xcodeproj/project.pbxproj +++ b/SectionKit.xcodeproj/project.pbxproj @@ -34,7 +34,6 @@ 5A0B777C26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */; }; 5A0B777E26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */; }; 5A0B778226B2A92C00B054D4 /* SingleItemSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */; }; - 5A0B778426B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */; }; 5A0B778626B2AB7800B054D4 /* BaseSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */; }; 5A0B778926B3EA4D00B054D4 /* ErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A0B778826B3EA4D00B054D4 /* ErrorTests.swift */; }; 5A31B8B726BAE8A900036A3F /* BaseSectionDataSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A31B8B526BAE8A300036A3F /* BaseSectionDataSourceTests.swift */; }; @@ -137,6 +136,7 @@ D93269A22BBBFC2400B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CA2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSourcePrefetching.swift */; }; D93269A32BBBFC2700B33C32 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175C92667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDataSource.swift */; }; D93269A42BBBFC2B00B33C32 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5AE175CF2667DA3F00D4DCE1 /* ListCollectionViewAdapter+UICollectionViewDragDelegate.swift */; }; + D952494D2BC6EDFB00108510 /* SingleModelSectionControllerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D952494C2BC6EDFB00108510 /* SingleModelSectionControllerTests.swift */; }; D9CCE9BF2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */; }; /* End PBXBuildFile section */ @@ -178,7 +178,6 @@ 5A0B777B26B2931700B054D4 /* CollectionViewSectionBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewSectionBatchOperationTests.swift; sourceTree = ""; }; 5A0B777D26B2944F00B054D4 /* CollectionViewBatchOperationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewBatchOperationTests.swift; sourceTree = ""; }; 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleItemSectionControllerTests.swift; sourceTree = ""; }; - 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleModelFlowLayoutSectionControllerTests.swift; sourceTree = ""; }; 5A0B778526B2AB7800B054D4 /* BaseSectionControllerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionControllerTests.swift; sourceTree = ""; }; 5A0B778826B3EA4D00B054D4 /* ErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorTests.swift; sourceTree = ""; }; 5A31B8B526BAE8A300036A3F /* BaseSectionDataSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseSectionDataSourceTests.swift; sourceTree = ""; }; @@ -284,6 +283,7 @@ D91425642BBBF74A0005E8CD /* SectionKitCompositionalLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionKitCompositionalLayout.swift; sourceTree = ""; }; D914257A2BBBF8130005E8CD /* BaseFlowLayoutSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionFlowDelegateTests.swift; sourceTree = ""; }; D914257B2BBBF8130005E8CD /* BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseFlowLayoutSectionControllerSectionFlowDelegateTests.swift; sourceTree = ""; }; + D952494C2BC6EDFB00108510 /* SingleModelSectionControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleModelSectionControllerTests.swift; sourceTree = ""; }; D9CCE9BE2BADF7C700EED204 /* NSCollectionLayoutSection+Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSCollectionLayoutSection+Empty.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -656,7 +656,7 @@ 5A31B8E126BC25A700036A3F /* ProtocolDefaultValuesSectionControllerTests.swift */, D90764CE2BC6E8140083306E /* ListSectionControllerTests.swift */, 5A0B778126B2A92C00B054D4 /* SingleItemSectionControllerTests.swift */, - 5A0B778326B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift */, + D952494C2BC6EDFB00108510 /* SingleModelSectionControllerTests.swift */, ); path = SectionController; sourceTree = ""; @@ -905,7 +905,6 @@ 5AB6642926A587AE004DC230 /* CollectionViewContextSizeTests.swift in Sources */, 5A31B8CF26BAE93900036A3F /* BaseSectionDropDelegateTests.swift in Sources */, 5A31B8BF26BAE8EE00036A3F /* BaseSectionControllerSectionDataSourcePrefetchingDelegateTests.swift in Sources */, - 5A0B778426B2AA2000B054D4 /* SingleModelFlowLayoutSectionControllerTests.swift in Sources */, 5A0B775926B0069700B054D4 /* BaseCollectionViewAdapterUICollectionViewDropDelegateTests.swift in Sources */, 5A0B776E26B19E8C00B054D4 /* MockSingleSectionCollectionViewAdapterDataSource.swift in Sources */, 5A8D3E5927E8D16200073712 /* MockCollectionViewAdapter.swift in Sources */, @@ -936,6 +935,7 @@ 5AA9D96326AAC65200679D88 /* ListCollectionViewAdapterUICollectionViewDataSourcePrefetchingTests.swift in Sources */, 5AE1761B2667DA7000D4DCE1 /* SectionIndexPathTests.swift in Sources */, 5AA9D96C26AAD05400679D88 /* ListCollectionViewAdapterUICollectionViewDelegateTests.swift in Sources */, + D952494D2BC6EDFB00108510 /* SingleModelSectionControllerTests.swift in Sources */, 5A31B8C726BAE91300036A3F /* ProtocolDefaultValuesSectionDelegateTests.swift in Sources */, 5A0B776A26B1826100B054D4 /* ListCollectionViewAdapterTests.swift in Sources */, 5A31B8B926BAE8C600036A3F /* BaseSectionControllerSectionDataSourceTests.swift in Sources */, From 1ae6656dc8882a11011fdc6f42336470136c4014 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 17 Apr 2024 00:03:27 +0200 Subject: [PATCH 19/24] fix assert message --- .../CompositionalLayout/SectionKitCompositionalLayout.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift index 8c119562..d1713597 100644 --- a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift +++ b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift @@ -12,7 +12,7 @@ final public class SectionKitCompositionalLayout: UICollectionViewCompositionalL var sections: (() -> [Section])? super.init { index, environment in guard let sections = sections?() else { - assertionFailure("The section provider doesn't set up correctly, please use the `CollectionViewCompositionalLayoutAdapter`") + assertionFailure("The section update closure doesn't set up correctly, please check the `CollectionViewAdapter`") return .empty } guard sections.count > index else { From 15458119e1c5c28cf9fe611f71e24ae53be02829 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 17 Apr 2024 00:05:56 +0200 Subject: [PATCH 20/24] improve assert message --- .../CompositionalLayout/SectionKitCompositionalLayout.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift index d1713597..71aa453d 100644 --- a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift +++ b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift @@ -12,7 +12,7 @@ final public class SectionKitCompositionalLayout: UICollectionViewCompositionalL var sections: (() -> [Section])? super.init { index, environment in guard let sections = sections?() else { - assertionFailure("The section update closure doesn't set up correctly, please check the `CollectionViewAdapter`") + assertionFailure("The section update closure doesn't set up correctly, please use the `CollectionViewAdapter`") return .empty } guard sections.count > index else { From 9e1437fec2e4bdcfc4de7438f59c28613f458e18 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Fri, 19 Apr 2024 16:59:00 +0200 Subject: [PATCH 21/24] make the layout provider nonoptional --- .../Names/NamesSectionController.swift | 2 +- ...istCollectionViewAdapter+Convenience.swift | 4 +- ...ionCollectionViewAdapter+Convenience.swift | 4 +- .../Generic/BaseSectionController.swift | 2 +- .../SectionController/SectionController.swift | 7 +- ...ollectionViewDelegateFlowLayoutTests.swift | 70 +++++++++---------- ...lDefaultValuesSectionControllerTests.swift | 3 +- .../TestUtilities/MockSectionController.swift | 5 +- 8 files changed, 48 insertions(+), 49 deletions(-) diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift index b14881d6..06a2f97c 100644 --- a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift @@ -5,7 +5,7 @@ final class NamesSectionController: ListSectionController< NamesSectionViewModelType, String > { - override var layoutProvider: SectionLayoutProvider? { + override var layoutProvider: SectionLayoutProvider { let layoutSize = NSCollectionLayoutSize( widthDimension: .fractionalWidth(1), heightDimension: .estimated(50) diff --git a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift index 2ddbd2d7..65398091 100644 --- a/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/ListCollectionViewAdapter/ListCollectionViewAdapter+Convenience.swift @@ -59,7 +59,7 @@ extension ListCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - return controller(at: indexPath)?.layoutProvider?.flowLayoutProvider + return controller(at: indexPath)?.layoutProvider.flowLayoutProvider } else { return controller(at: indexPath)?.flowDelegate } @@ -68,7 +68,7 @@ extension ListCollectionViewAdapter { @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - return controller(at: index)?.layoutProvider?.flowLayoutProvider + return controller(at: index)?.layoutProvider.flowLayoutProvider } else { return controller(at: index)?.flowDelegate } diff --git a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift index d6666281..a4140864 100644 --- a/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift +++ b/SectionKit/Sources/CollectionViewAdapter/SingleSectionCollectionViewAdapter/SingleSectionCollectionViewAdapter+Convenience.swift @@ -59,7 +59,7 @@ extension SingleSectionCollectionViewAdapter { @inlinable public func flowDelegate(at indexPath: IndexPath) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - return controller(at: indexPath)?.layoutProvider?.flowLayoutProvider + return controller(at: indexPath)?.layoutProvider.flowLayoutProvider } else { return controller(at: indexPath)?.flowDelegate } @@ -68,7 +68,7 @@ extension SingleSectionCollectionViewAdapter { @inlinable public func flowDelegate(at index: Int) -> SectionFlowDelegate? { if #available(iOS 13.0, *) { - return controller(at: index)?.layoutProvider?.flowLayoutProvider + return controller(at: index)?.layoutProvider.flowLayoutProvider } else { return controller(at: index)?.flowDelegate } diff --git a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift index 475d538f..7ef4035b 100644 --- a/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift +++ b/SectionKit/Sources/SectionController/Generic/BaseSectionController.swift @@ -37,7 +37,7 @@ open class BaseSectionController: SectionController, open var dropDelegate: SectionDropDelegate? { self } @available(iOS 13.0, *) - open var layoutProvider: SectionLayoutProvider? { .flowLayout(self) } + open var layoutProvider: SectionLayoutProvider { .flowLayout(self) } open func didUpdate(model: Any) { } diff --git a/SectionKit/Sources/SectionController/SectionController.swift b/SectionKit/Sources/SectionController/SectionController.swift index b49bb6fd..7af145c9 100644 --- a/SectionKit/Sources/SectionController/SectionController.swift +++ b/SectionKit/Sources/SectionController/SectionController.swift @@ -28,7 +28,7 @@ public protocol SectionController: AnyObject { var dropDelegate: SectionDropDelegate? { get } @available(iOS 13.0, *) - var layoutProvider: SectionLayoutProvider? { get } + var layoutProvider: SectionLayoutProvider { get } /// The model of this section controller changed. func didUpdate(model: Any) @@ -47,14 +47,11 @@ extension SectionController { @available(iOS 11.0, *) public var dropDelegate: SectionDropDelegate? { nil } - - @available(iOS 13.0, *) - public var layoutProvider: SectionLayoutProvider? { nil } } @available(iOS 13.0, *) public enum SectionLayoutProvider { - case flowLayout(FlowLayoutProvider) + case flowLayout(FlowLayoutProvider?) case compositionalLayout(CompositionalLayoutProvider) } diff --git a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift index ace37e1c..ab29f68c 100644 --- a/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift +++ b/SectionKit/Tests/CollectionViewAdapter/UICollectionViewDelegateFlowLayout/BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.swift @@ -2,19 +2,19 @@ import UIKit import XCTest -internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: XCTestCase { +class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: XCTestCase { override func setUpWithError() throws { try super.setUpWithError() continueAfterFailure = false try skipIfNeeded() } - internal func skipIfNeeded() throws { + func skipIfNeeded() throws { guard Self.self === BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests.self else { return } throw XCTSkip("Tests from base class are skipped") } - internal func createCollectionView( + func createCollectionView( frame: CGRect = .zero, collectionViewLayout layout: UICollectionViewLayout? = nil ) -> UICollectionView { @@ -22,7 +22,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func createCollectionViewAdapter( + func createCollectionViewAdapter( collectionView: UICollectionView, sections: [Section] = [], viewController: UIViewController? = nil, @@ -34,7 +34,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - sizeForItem @MainActor - internal func testSizeForItemWithDelegate() throws { + func testSizeForItemWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: mockLayout) @@ -67,7 +67,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testSizeForItemWithoutDelegateButWithFlowLayout() throws { + func testSizeForItemWithoutDelegateButWithFlowLayout() throws { let itemSize = CGSize(width: 1, height: 2) let layout = UICollectionViewFlowLayout() layout.itemSize = itemSize @@ -78,7 +78,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -90,8 +90,8 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testSizeForItemWithoutDelegateAndFlowLayout() throws { - let layout = UICollectionViewLayout() + func testSizeForItemWithoutDelegateAndFlowLayout() throws { + let layout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: layout) let itemIndexPath = IndexPath(item: 0, section: 0) let adapter = try createCollectionViewAdapter( @@ -99,7 +99,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -113,7 +113,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - inset @MainActor - internal func testInsetWithDelegate() throws { + func testInsetWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: mockLayout) @@ -144,7 +144,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testInsetWithoutDelegateButWithFlowLayout() throws { + func testInsetWithoutDelegateButWithFlowLayout() throws { let sectionInset = UIEdgeInsets(top: 1, left: 2, bottom: 4, right: 8) let layout = UICollectionViewFlowLayout() layout.sectionInset = sectionInset @@ -154,7 +154,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -166,7 +166,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testInsetWithoutDelegateAndFlowLayout() throws { + func testInsetWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) let adapter = try createCollectionViewAdapter( @@ -174,7 +174,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -188,7 +188,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - minimumLineSpacing @MainActor - internal func testMinimumLineSpacingWithDelegate() throws { + func testMinimumLineSpacingWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: mockLayout) @@ -219,7 +219,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testMinimumLineSpacingWithoutDelegateButWithFlowLayout() throws { + func testMinimumLineSpacingWithoutDelegateButWithFlowLayout() throws { let lineSpacing: CGFloat = 1 let layout = UICollectionViewFlowLayout() layout.minimumLineSpacing = lineSpacing @@ -229,7 +229,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -241,7 +241,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testMinimumLineSpacingWithoutDelegateAndFlowLayout() throws { + func testMinimumLineSpacingWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) let adapter = try createCollectionViewAdapter( @@ -249,7 +249,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -263,7 +263,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - minimumInteritemSpacing @MainActor - internal func testMinimumInteritemSpacingWithDelegate() throws { + func testMinimumInteritemSpacingWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: mockLayout) @@ -294,7 +294,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testMinimumInteritemSpacingWithoutDelegateButWithFlowLayout() throws { + func testMinimumInteritemSpacingWithoutDelegateButWithFlowLayout() throws { let interitemSpacing: CGFloat = 1 let layout = UICollectionViewFlowLayout() layout.minimumInteritemSpacing = interitemSpacing @@ -304,7 +304,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -316,7 +316,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testMinimumInteritemSpacingWithoutDelegateAndFlowLayout() throws { + func testMinimumInteritemSpacingWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) let adapter = try createCollectionViewAdapter( @@ -324,7 +324,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -338,7 +338,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - referenceSizeForHeader @MainActor - internal func testReferenceSizeForHeaderWithDelegate() throws { + func testReferenceSizeForHeaderWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: mockLayout) @@ -369,7 +369,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testReferenceSizeForHeaderWithoutDelegateButWithFlowLayout() throws { + func testReferenceSizeForHeaderWithoutDelegateButWithFlowLayout() throws { let headerSize = CGSize(width: 1, height: 2) let layout = UICollectionViewFlowLayout() layout.headerReferenceSize = headerSize @@ -379,7 +379,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -391,7 +391,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testReferenceSizeForHeaderWithoutDelegateAndFlowLayout() throws { + func testReferenceSizeForHeaderWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) let adapter = try createCollectionViewAdapter( @@ -399,7 +399,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -413,7 +413,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: // MARK: - referenceSizeForFooter @MainActor - internal func testReferenceSizeForFooterWithDelegate() throws { + func testReferenceSizeForFooterWithDelegate() throws { let testExpectation = expectation(description: "Should invoke flow layout delegate") let mockLayout = UICollectionViewFlowLayout() let collectionView = createCollectionView(collectionViewLayout: mockLayout) @@ -444,7 +444,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testReferenceSizeForFooterWithoutDelegateButWithFlowLayout() throws { + func testReferenceSizeForFooterWithoutDelegateButWithFlowLayout() throws { let footerSize = CGSize(width: 1, height: 2) let layout = UICollectionViewFlowLayout() layout.footerReferenceSize = footerSize @@ -454,7 +454,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] @@ -466,7 +466,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: } @MainActor - internal func testReferenceSizeForFooterWithoutDelegateAndFlowLayout() throws { + func testReferenceSizeForFooterWithoutDelegateAndFlowLayout() throws { let layout = UICollectionViewLayout() let collectionView = createCollectionView(collectionViewLayout: layout) let adapter = try createCollectionViewAdapter( @@ -474,7 +474,7 @@ internal class BaseCollectionViewAdapterUICollectionViewDelegateFlowLayoutTests: sections: [ Section(id: "", model: "", controller: { let sectionController = MockSectionController() - sectionController.layoutProvider = nil + sectionController.layoutProvider = .flowLayout(nil) return sectionController }) ] diff --git a/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift b/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift index d01408be..dde22eac 100644 --- a/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/ProtocolDefaultValuesSectionControllerTests.swift @@ -9,7 +9,8 @@ final class ProtocolDefaultValuesSectionControllerTests: XCTestCase { super.setUp() class DefaultSectionController: SectionController { var context: CollectionViewContext? - var dataSource: SectionDataSource = MockSectionDataSource() + let dataSource: SectionDataSource = MockSectionDataSource() + let layoutProvider: SectionLayoutProvider = .flowLayout(nil) func didUpdate(model: Any) { } } sut = DefaultSectionController() diff --git a/SectionKit/Tests/TestUtilities/MockSectionController.swift b/SectionKit/Tests/TestUtilities/MockSectionController.swift index 23ab185b..f5ffef42 100644 --- a/SectionKit/Tests/TestUtilities/MockSectionController.swift +++ b/SectionKit/Tests/TestUtilities/MockSectionController.swift @@ -42,9 +42,10 @@ internal class MockSectionController: SectionController { return MockErrorHandler() }() - internal lazy var layoutProvider: SectionLayoutProvider? = { + @available(iOS 13.0, *) + internal lazy var layoutProvider: SectionLayoutProvider = { XCTFail("layoutProvider is not set") - return nil + return .flowLayout(nil) }() // MARK: - didUpdate From cbfbfe18ec330e50c9b26535379c8736b1174453 Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Fri, 19 Apr 2024 17:14:11 +0200 Subject: [PATCH 22/24] update better naming --- .../VanillaSwiftExamples/Names/NamesSectionController.swift | 2 +- .../Sources/SectionController/SectionController.swift | 6 +++--- .../CompositionalLayout/SectionKitCompositionalLayout.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift index 06a2f97c..5830afa3 100644 --- a/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift +++ b/Example/VanillaSwiftExamples/Sources/VanillaSwiftExamples/Names/NamesSectionController.swift @@ -36,7 +36,7 @@ final class NamesSectionController: ListSectionController< layout.boundarySupplementaryItems = [] } return .compositionalLayout( - .init(layoutSection: { _ in layout }) + .init { _ in layout } ) } diff --git a/SectionKit/Sources/SectionController/SectionController.swift b/SectionKit/Sources/SectionController/SectionController.swift index 7af145c9..88cd4834 100644 --- a/SectionKit/Sources/SectionController/SectionController.swift +++ b/SectionKit/Sources/SectionController/SectionController.swift @@ -64,12 +64,12 @@ public struct CompositionalLayoutProvider { /// - Parameters: /// - layoutEnvironment: the environment value for the layout /// - Returns: The layout for the section - var layoutSection: (_ layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection + var layoutSectionProvider: (_ layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection public init( - layoutSection: @escaping (any NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection + layoutSectionProvider: @escaping (any NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection ) { - self.layoutSection = layoutSection + self.layoutSectionProvider = layoutSectionProvider } } diff --git a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift index 71aa453d..d5d081e8 100644 --- a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift +++ b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift @@ -23,7 +23,7 @@ final public class SectionKitCompositionalLayout: UICollectionViewCompositionalL assertionFailure("Please set the layout provider with `CompositionalLayoutProvider`") return .empty } - return provider.layoutSection(environment) + return provider.layoutSectionProvider(environment) } sections = { [weak self] in self?.sections?() ?? [] From a6c9f71e5487ff212349ee9feaf91ecbc2d9e2be Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Fri, 19 Apr 2024 17:41:26 +0200 Subject: [PATCH 23/24] make better assertion --- .../CompositionalLayout/SectionKitCompositionalLayout.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift index d5d081e8..d507b952 100644 --- a/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift +++ b/SectionKit/Sources/Utility/CompositionalLayout/SectionKitCompositionalLayout.swift @@ -20,7 +20,8 @@ final public class SectionKitCompositionalLayout: UICollectionViewCompositionalL return .empty } guard case .compositionalLayout(let provider) = sections[index].controller.layoutProvider else { - assertionFailure("Please set the layout provider with `CompositionalLayoutProvider`") + let sectionType = String(describing: type(of: sections[index].controller)) + assertionFailure("Please set the layout provider with `CompositionalLayoutProvider` in \(sectionType)") return .empty } return provider.layoutSectionProvider(environment) From 158322570c9254785054592fb9597527dbb3369d Mon Sep 17 00:00:00 2001 From: Calvin Chang Date: Wed, 22 May 2024 11:56:58 +0200 Subject: [PATCH 24/24] fix tests --- .../ColorsSectionControllerSnapshotTests.swift | 2 +- .../NumbersSectionControllerSnapshotTests.swift | 2 +- .../Tests/SectionController/BaseSectionControllerTests.swift | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/ColorsSectionControllerSnapshotTests.swift b/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/ColorsSectionControllerSnapshotTests.swift index b1fcc521..584dfd8f 100644 --- a/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/ColorsSectionControllerSnapshotTests.swift +++ b/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/ColorsSectionControllerSnapshotTests.swift @@ -3,8 +3,8 @@ import SnapshotTesting import TestUtilities import XCTest -@MainActor final class ColorsSectionControllerSnapshotTests: XCTestCase { + @MainActor func testDefaultViewModel() { let sectionController = ColorsSectionController(model: [.red, .green, .blue]) let container = SectionSnapshotContainer(sectionController: sectionController, width: 375) diff --git a/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/NumbersSectionControllerSnapshotTests.swift b/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/NumbersSectionControllerSnapshotTests.swift index 88263016..838c5425 100644 --- a/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/NumbersSectionControllerSnapshotTests.swift +++ b/Example/VanillaSwiftExamples/Tests/VanillaSwiftExamplesSnapshotTests/NumbersSectionControllerSnapshotTests.swift @@ -3,8 +3,8 @@ import SnapshotTesting import TestUtilities import XCTest -@MainActor final class NumbersSectionControllerSnapshotTests: XCTestCase { + @MainActor func testDefaultViewModel() { let model = NumbersSectionViewModel(numbers: Array(0..<10), navigation: MockNumbersSectionNavigation()) let sectionController = NumbersSectionController(model: model) diff --git a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift index 85b8522c..4e6e3384 100644 --- a/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift +++ b/SectionKit/Tests/SectionController/BaseSectionControllerTests.swift @@ -27,13 +27,14 @@ final class BaseSectionControllerTests: XCTestCase { XCTAssert(sectionController.delegate === sectionController) } - internal func testFlowDelegateIsSelf() { + @MainActor + func testFlowDelegateIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.flowDelegate === sectionController) } - @available(iOS 11.0, *) @MainActor + @available(iOS 11.0, *) func testDragDelegateIsSelf() { let sectionController = BaseSectionController() XCTAssert(sectionController.dragDelegate === sectionController)