From d3c6cc69d289675f154dd4352f9d533605e277d7 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Sat, 20 Dec 2025 09:19:43 +0800 Subject: [PATCH 1/6] Add Animations showcase --- .../QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift index ba4d014..a0de97f 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift @@ -37,7 +37,11 @@ struct ShowcaseApp: View { [ StateManagementView.self ]), - + SCSection( + "Animations", + [ + UpdatingWithAnimationView.self + ]), SCSection( "Alignment", [ From 953c25e6397ca962ed0b0cfc9e03721aae59d522 Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Sat, 20 Dec 2025 09:24:47 +0800 Subject: [PATCH 2/6] Rename to viewType --- .../QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift index a0de97f..1e51027 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift @@ -105,14 +105,14 @@ struct ShowcaseApp: View { private struct ShowcaseViewRepresentable: UIViewRepresentable { - let view: UIView.Type + let viewType: UIView.Type init(_ viewType: UIView.Type) { - self.view = viewType + self.viewType = viewType } func makeUIView(context: Context) -> some UIView { - view.init() as UIView + viewType.init() as UIView } func updateUIView(_ uiView: UIViewType, context: Context) { From 3b7f2c040ace2c6af599c9cc3cb09999f1c7423a Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Sat, 20 Dec 2025 09:35:42 +0800 Subject: [PATCH 3/6] Support UIViewController.Type for showcase --- .../__showcase__/QuickLayoutShowcaseApp.swift | 70 ++++++++++++++++--- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift index 1e51027..a03655c 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift @@ -119,20 +119,68 @@ private struct ShowcaseViewRepresentable: UIViewRepresentable { } } +private struct ShowcaseViewControllerRepresentable: UIViewControllerRepresentable { + + let viewControllerType: UIViewController.Type + + init(_ viewControllerType: UIViewController.Type) { + self.viewControllerType = viewControllerType + } + + func makeUIViewController(context: Context) -> some UIViewController { + viewControllerType.init() as UIViewController + } + + func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { + } +} + +private enum ShowcaseType { + case view(UIView.Type) + case viewController(UIViewController.Type) + + var underlyingType: Any.Type { + switch self { + case let .view(viewType): + return viewType + case let .viewController(viewControllerType): + return viewControllerType + } + } +} + +private protocol ShowcaseTypeConvertable { + static var showcaseType: ShowcaseType { get } +} + +extension UIView: ShowcaseTypeConvertable { + fileprivate static var showcaseType: ShowcaseType { .view(Self.self) } +} + +extension UIViewController: ShowcaseTypeConvertable { + fileprivate static var showcaseType: ShowcaseType { .viewController(Self.self) } +} + private struct SCShowcase: Identifiable, Hashable { let id = UUID() - let viewType: UIView.Type + let showcaseType: ShowcaseType let label: String - init(viewType: UIView.Type) { - self.viewType = viewType - self.label = String(describing: viewType).splittingCamelCase() + init(showcaseType: ShowcaseType) { + self.showcaseType = showcaseType + self.label = String(describing: showcaseType.underlyingType).splittingCamelCase() } @MainActor + @ViewBuilder func view() -> some View { - ShowcaseViewRepresentable(viewType) + switch showcaseType { + case let .view(viewType): + ShowcaseViewRepresentable(viewType) + case let .viewController(viewControllerType): + ShowcaseViewControllerRepresentable(viewControllerType) + } } static func == (lhs: SCShowcase, rhs: SCShowcase) -> Bool { @@ -146,7 +194,13 @@ private struct SCShowcase: Identifiable, Hashable { private extension String { func splittingCamelCase() -> String { - let stripped = self.hasSuffix("View") ? String(self.dropLast(4)) : self + let stripped = self.hasSuffix("View") + ? String(self.dropLast(4)) + : ( + self.hasSuffix("ViewController") + ? String(self.dropLast(14)) + : self + ) // Split by uppercase letters let words = stripped.reduce("") { result, char in @@ -168,9 +222,9 @@ private struct SCSection: Identifiable, Hashable { let showscases: [SCShowcase] let title: String - init(_ title: String, _ showcases: [UIView.Type]) { + init(_ title: String, _ showcases: [ShowcaseTypeConvertable.Type]) { self.title = title - self.showscases = showcases.map { SCShowcase(viewType: $0) } + self.showscases = showcases.map { SCShowcase(showcaseType: $0.showcaseType) } } } From 1f306a711ad67130c913464a989e831fca3acefe Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Sat, 20 Dec 2025 09:35:52 +0800 Subject: [PATCH 4/6] Add List showcase --- .../QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift index a03655c..d9481a5 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift @@ -42,6 +42,11 @@ struct ShowcaseApp: View { [ UpdatingWithAnimationView.self ]), + SCSection( + "List", + [ + BarsListViewController.self + ]), SCSection( "Alignment", [ From bdc26e8afec81646b9b74fdce5337177dc3c615c Mon Sep 17 00:00:00 2001 From: nuomi1 Date: Sat, 20 Dec 2025 09:39:48 +0800 Subject: [PATCH 5/6] Use view.bounds.size as layout.itemSize --- .../4-ListExample/BarsListViewController.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsListViewController.swift b/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsListViewController.swift index 8c94f63..8e7c6d2 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsListViewController.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/4-ListExample/BarsListViewController.swift @@ -10,13 +10,15 @@ import UIKit final class BarsListViewController: UIViewController { private var dataSource: UICollectionViewDiffableDataSource? - private lazy var collectionView = { + private lazy var layout = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical layout.minimumLineSpacing = 0 layout.minimumLineSpacing = 0 - // patternlint-disable-next-line ig-avoid-uiscreen-bounds-swift - layout.itemSize = UIScreen.main.bounds.size + return layout + }() + + private lazy var collectionView = { let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) collectionView.register(BarCardViewCell.self, forCellWithReuseIdentifier: BarCardViewCell.reuseIdentifier) @@ -37,6 +39,13 @@ final class BarsListViewController: UIViewController { self.view = collectionView } + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + if layout.itemSize != view.bounds.size { + layout.itemSize = view.bounds.size + } + } + func configureDataSource() { dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { (collectionView: UICollectionView, indexPath: IndexPath, item: BarModel) -> UICollectionViewCell? in guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: BarCardViewCell.reuseIdentifier, for: indexPath) as? BarCardViewCell else { From 1a8ac921b2b37262f1d71d217c03c1e93f62bff9 Mon Sep 17 00:00:00 2001 From: Constantine Fry Date: Mon, 19 Jan 2026 12:09:53 +0000 Subject: [PATCH 6/6] Fix CI error --- .../__showcase__/QuickLayoutShowcaseApp.swift | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift index d9481a5..a8562c9 100644 --- a/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift +++ b/Sources/QuickLayout/QuickLayout/__showcase__/QuickLayoutShowcaseApp.swift @@ -154,6 +154,7 @@ private enum ShowcaseType { } } +@MainActor private protocol ShowcaseTypeConvertable { static var showcaseType: ShowcaseType { get } } @@ -199,13 +200,12 @@ private struct SCShowcase: Identifiable, Hashable { private extension String { func splittingCamelCase() -> String { - let stripped = self.hasSuffix("View") + let stripped = + self.hasSuffix("View") ? String(self.dropLast(4)) - : ( - self.hasSuffix("ViewController") - ? String(self.dropLast(14)) - : self - ) + : (self.hasSuffix("ViewController") + ? String(self.dropLast(14)) + : self) // Split by uppercase letters let words = stripped.reduce("") { result, char in @@ -222,6 +222,7 @@ private extension String { } } +@MainActor private struct SCSection: Identifiable, Hashable { let id = UUID() let showscases: [SCShowcase]