From 7340ee73639b8899b9e4a9c0970a48861195414b Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 18 Nov 2022 11:16:05 -0600 Subject: [PATCH] refactored out collectionview Signed-off-by: Matt Bruce --- VDS.xcodeproj/project.pbxproj | 4 + VDS/Classes/SelfSizingCollectionView.swift | 76 +++++++++++++++++++ .../Buttons/ButtonGroup/ButtonGroup.swift | 66 ---------------- 3 files changed, 80 insertions(+), 66 deletions(-) create mode 100644 VDS/Classes/SelfSizingCollectionView.swift diff --git a/VDS.xcodeproj/project.pbxproj b/VDS.xcodeproj/project.pbxproj index 519ed7eb..0244a9b3 100644 --- a/VDS.xcodeproj/project.pbxproj +++ b/VDS.xcodeproj/project.pbxproj @@ -60,6 +60,7 @@ EAB1D2EA28AE84AA00DAE764 /* UIControlPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB1D2E928AE84AA00DAE764 /* UIControlPublisher.swift */; }; EAB5FED429267EB300998C17 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FED329267EB300998C17 /* UIView.swift */; }; EAB5FEED2927E1B200998C17 /* ButtonGroupPositionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FEEC2927E1B200998C17 /* ButtonGroupPositionLayout.swift */; }; + EAB5FEF12927F4AA00998C17 /* SelfSizingCollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB5FEF02927F4AA00998C17 /* SelfSizingCollectionView.swift */; }; EAC9257D29119B5400091998 /* TextLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC9257C29119B5400091998 /* TextLink.swift */; }; EAC925832911B35400091998 /* TextLinkCaret.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAC925822911B35300091998 /* TextLinkCaret.swift */; }; EAC925842911C63100091998 /* Colorable.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA5EEDF28F49DB3003B3210 /* Colorable.swift */; }; @@ -151,6 +152,7 @@ EAB1D2E928AE84AA00DAE764 /* UIControlPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIControlPublisher.swift; sourceTree = ""; }; EAB5FED329267EB300998C17 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; EAB5FEEC2927E1B200998C17 /* ButtonGroupPositionLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonGroupPositionLayout.swift; sourceTree = ""; }; + EAB5FEF02927F4AA00998C17 /* SelfSizingCollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelfSizingCollectionView.swift; sourceTree = ""; }; EAC9257C29119B5400091998 /* TextLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextLink.swift; sourceTree = ""; }; EAC925822911B35300091998 /* TextLinkCaret.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextLinkCaret.swift; sourceTree = ""; }; EAC925872911C9DE00091998 /* TextEntryField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextEntryField.swift; sourceTree = ""; }; @@ -356,6 +358,7 @@ EA3361B5288B2A410071C351 /* Control.swift */, EAF7F09F289AB7EC00B287F5 /* View.swift */, EA4DB18428CA967F00103EE3 /* SelectorGroupHandlerBase.swift */, + EAB5FEF02927F4AA00998C17 /* SelfSizingCollectionView.swift */, ); path = Classes; sourceTree = ""; @@ -693,6 +696,7 @@ EA33623E2892EE950071C351 /* UIDevice.swift in Sources */, EA3362302891EB4A0071C351 /* Fonts.swift in Sources */, EAF7F0AD289B142900B287F5 /* StrikeThroughLabelAttribute.swift in Sources */, + EAB5FEF12927F4AA00998C17 /* SelfSizingCollectionView.swift in Sources */, EA3361B8288B2AAA0071C351 /* ViewProtocol.swift in Sources */, EA3361BF288B2EA60071C351 /* Handlerable.swift in Sources */, EA3361A8288B23300071C351 /* UIColor.swift in Sources */, diff --git a/VDS/Classes/SelfSizingCollectionView.swift b/VDS/Classes/SelfSizingCollectionView.swift new file mode 100644 index 00000000..5722d477 --- /dev/null +++ b/VDS/Classes/SelfSizingCollectionView.swift @@ -0,0 +1,76 @@ +// +// SelfSizingCollectionView.swift +// VDS +// +// Created by Matt Bruce on 11/18/22. +// + +import Foundation +import UIKit + +final class SelfSizingCollectionView: UICollectionView { + + private var contentSizeObservation: NSKeyValueObservation? + + // MARK: - Lifecycle + + override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { + super.init(frame: frame, collectionViewLayout: layout) + self.setupContentSizeObservation() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + self.setupContentSizeObservation() + } + + // MARK: - UIView + + override var intrinsicContentSize: CGSize { + let contentSize = self.contentSize + //print(#function, contentSize) + return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height) + } + + override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { + //print(type(of: self), #function) + super.traitCollectionDidChange(previousTraitCollection) + + // We need to handle any change that will affect layout and/or anything that affects size of a UILabel + if self.traitCollection.hasDifferentTextAppearance(comparedTo: previousTraitCollection) { + self.collectionViewLayout.invalidateLayout() + } + } + + override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize { + let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority) + //print(type(of: self), #function, targetSize, "->", size) + return size + } + + // MARK: - Private + + private func setupContentSizeObservation() { + // Observing the value of contentSize seems to be the only reliable way to get the contentSize after the collection view lays out its subviews. + self.contentSizeObservation = self.observe(\.contentSize, options: [.old, .new]) { [weak self] _, change in + // If we don't specify `options: [.old, .new]`, the change.oldValue and .newValue will always be `nil`. + if change.newValue != change.oldValue { + self?.invalidateIntrinsicContentSize() + } + } + } +} + +extension UITraitCollection { + + func hasDifferentTextAppearance(comparedTo traitCollection: UITraitCollection?) -> Bool { + var result = self.preferredContentSizeCategory != traitCollection?.preferredContentSizeCategory + + if #available(iOS 13.0, *) { + result = result || self.legibilityWeight != traitCollection?.legibilityWeight + } + + return result + } +} + diff --git a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift index 0ff514cb..12d08bf7 100644 --- a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift +++ b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift @@ -166,69 +166,3 @@ open class ButtonGroup: View, UICollectionViewDataSource, UICollectionViewDelega itemSpacing } } - -final class SelfSizingCollectionView: UICollectionView { - - private var contentSizeObservation: NSKeyValueObservation? - - // MARK: - Lifecycle - - override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) { - super.init(frame: frame, collectionViewLayout: layout) - self.setupContentSizeObservation() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - self.setupContentSizeObservation() - } - - // MARK: - UIView - - override var intrinsicContentSize: CGSize { - let contentSize = self.contentSize - //print(#function, contentSize) - return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height) - } - - override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { - //print(type(of: self), #function) - super.traitCollectionDidChange(previousTraitCollection) - - // We need to handle any change that will affect layout and/or anything that affects size of a UILabel - if self.traitCollection.hasDifferentTextAppearance(comparedTo: previousTraitCollection) { - self.collectionViewLayout.invalidateLayout() - } - } - - override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize { - let size = super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority) - //print(type(of: self), #function, targetSize, "->", size) - return size - } - - // MARK: - Private - - private func setupContentSizeObservation() { - // Observing the value of contentSize seems to be the only reliable way to get the contentSize after the collection view lays out its subviews. - self.contentSizeObservation = self.observe(\.contentSize, options: [.old, .new]) { [weak self] _, change in - // If we don't specify `options: [.old, .new]`, the change.oldValue and .newValue will always be `nil`. - if change.newValue != change.oldValue { - self?.invalidateIntrinsicContentSize() - } - } - } -} - -extension UITraitCollection { - - func hasDifferentTextAppearance(comparedTo traitCollection: UITraitCollection?) -> Bool { - var result = self.preferredContentSizeCategory != traitCollection?.preferredContentSizeCategory - - if #available(iOS 13.0, *) { - result = result || self.legibilityWeight != traitCollection?.legibilityWeight - } - - return result - } -}