From 441971d2f917ff5ebdd97437fa4878e18dba9893 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 09:20:17 -0600 Subject: [PATCH 01/14] updated to fix issue for attributedText Signed-off-by: Matt Bruce --- .../Selector/SelectorItemBase.swift | 2 - VDS/Components/Label/Label.swift | 118 ++++++++++++------ VDS/Components/RadioBox/RadioBoxItem.swift | 3 - 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/VDS/BaseClasses/Selector/SelectorItemBase.swift b/VDS/BaseClasses/Selector/SelectorItemBase.swift index 9ca86d8c..869c40e0 100644 --- a/VDS/BaseClasses/Selector/SelectorItemBase.swift +++ b/VDS/BaseClasses/Selector/SelectorItemBase.swift @@ -102,7 +102,6 @@ open class SelectorItemBase: Control, Errorable, /// Instead of use labelText and labelTextAttirbutes, this is a fully baked NSAttributedString with both text and attributes. open var labelAttributedText: NSAttributedString? { didSet { - label.useAttributedText = !(labelAttributedText?.string.isEmpty ?? true) label.attributedText = labelAttributedText setNeedsUpdate() } @@ -117,7 +116,6 @@ open class SelectorItemBase: Control, Errorable, /// Instead of use childText and childTextAttirbutes, this is a fully baked NSAttributedString with both text and attributes. open var childAttributedText: NSAttributedString? { didSet { - childLabel.useAttributedText = !(childAttributedText?.string.isEmpty ?? true) childLabel.attributedText = childAttributedText setNeedsUpdate() } diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index 67e53abe..c998c70b 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -42,6 +42,13 @@ open class Label: UILabel, ViewProtocol, UserInfoable { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- + private enum TextSetMode { + case text + case attributedText + } + + private var textSetMode: TextSetMode = .text + private var initialSetupPerformed = false private var edgeInsets: UIEdgeInsets { textStyle.edgeInsets } @@ -102,10 +109,6 @@ open class Label: UILabel, ViewProtocol, UserInfoable { //-------------------------------------------------- /// Key of whether or not updateView() is called in setNeedsUpdate() open var shouldUpdateView: Bool = true - - /// Determines if the label should use its own attributedText property instead of rendering the attributedText propert - /// based of other local properties, such as textStyle, textColor, surface, etc... The default value is false. - open var useAttributedText: Bool = false /// Will determine if a scaled font should be used for the font. open var useScaledFont: Bool = false { didSet { setNeedsUpdate() }} @@ -132,15 +135,25 @@ open class Label: UILabel, ViewProtocol, UserInfoable { private var _text: String? /// Text that will be used in the label. - override open var text: String? { - get { _text } + override public var text: String! { + get { super.text } set { - if _text != newValue || newValue != attributedText?.string { - _text = newValue - useAttributedText = false - attributes?.removeAll() - setNeedsUpdate() - } + // When text is set, we may need to re-style it as attributedText + // with the correct paragraph style to achieve the desired line height. + textSetMode = .text + attributes?.removeAll() + styleText(newValue) + } + } + + ///AttributedText that will be used in the label. + override public var attributedText: NSAttributedString? { + get { super.attributedText } + set { + // When text is set, we may need to re-style it as attributedText + // with the correct paragraph style to achieve the desired line height. + textSetMode = .attributedText + styleAttributedText(newValue) } } @@ -200,30 +213,13 @@ open class Label: UILabel, ViewProtocol, UserInfoable { } open func updateView() { - if !useAttributedText { - if let text { - accessibilityCustomActions = [] - - //create the primary string - let mutableText = NSMutableAttributedString.mutableText(for: text, - textStyle: textStyle, - useScaledFont: useScaledFont, - textColor: textColorConfiguration.getColor(self), - alignment: textAlignment, - lineBreakMode: lineBreakMode) - - applyAttributes(mutableText) - - //set the attributed text - attributedText = mutableText - - //force a drawText - setNeedsDisplay() - - setNeedsLayout() - layoutIfNeeded() - } - } + restyleText() + + //force a drawText + setNeedsDisplay() + + setNeedsLayout() + layoutIfNeeded() } open func updateAccessibility() { @@ -269,6 +265,56 @@ open class Label: UILabel, ViewProtocol, UserInfoable { //-------------------------------------------------- // MARK: - Private Methods //-------------------------------------------------- + private func restyleText() { + if textSetMode == .text { + styleText(text) + } else { + styleAttributedText(attributedText) + } + } + + private func styleText(_ newValue: String!) { + defer { invalidateIntrinsicContentSize() } + guard let newValue else { + // We don't need to use attributed text + super.attributedText = nil + super.text = newValue + return + } + + accessibilityCustomActions = [] + + //create the primary string + let mutableText = NSMutableAttributedString.mutableText(for: newValue, + textStyle: textStyle, + useScaledFont: useScaledFont, + textColor: textColorConfiguration.getColor(self), + alignment: textAlignment, + lineBreakMode: lineBreakMode) + + applyAttributes(mutableText) + + // Set attributed text to match typography + super.attributedText = mutableText + + } + + private func styleAttributedText(_ newValue: NSAttributedString?) { + defer { invalidateIntrinsicContentSize() } + guard let newValue = newValue else { + // We don't need any additional styling + super.attributedText = newValue + return + } + + var mutableText = NSMutableAttributedString(attributedString: newValue) + + applyAttributes(mutableText) + + // Modify attributed text to match typography + super.attributedText = newValue + } + private func applyAttributes(_ mutableAttributedString: NSMutableAttributedString) { actions = [] diff --git a/VDS/Components/RadioBox/RadioBoxItem.swift b/VDS/Components/RadioBox/RadioBoxItem.swift index 81f3f709..cfeb54e6 100644 --- a/VDS/Components/RadioBox/RadioBoxItem.swift +++ b/VDS/Components/RadioBox/RadioBoxItem.swift @@ -100,7 +100,6 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { /// If provided, the RadioBox textAttributedText will be rendered. open var textAttributedText: NSAttributedString? { didSet { - textLabel.useAttributedText = !(textAttributedText?.string.isEmpty ?? true) textLabel.attributedText = textAttributedText setNeedsUpdate() } @@ -115,7 +114,6 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { /// If provided, the RadioBox subTextAttributedText will be rendered. open var subTextAttributedText: NSAttributedString? { didSet { - subTextLabel.useAttributedText = !(subTextAttributedText?.string.isEmpty ?? true) subTextLabel.attributedText = subTextAttributedText setNeedsUpdate() } @@ -130,7 +128,6 @@ open class RadioBoxItem: Control, Changeable, FormFieldable { /// If provided, the RadioBox subTextRightAttributedText will be rendered. open var subTextRightAttributedText: NSAttributedString? { didSet { - subTextRightLabel.useAttributedText = !(subTextRightAttributedText?.string.isEmpty ?? true) subTextRightLabel.attributedText = subTextRightAttributedText setNeedsUpdate() } From 0fffd3811396b7120575501620e7af1a71fe8cb2 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 10:08:12 -0600 Subject: [PATCH 02/14] updated initialSetup Signed-off-by: Matt Bruce --- VDS/Components/Buttons/ButtonBase.swift | 1 + VDS/Components/TextFields/TextArea/TextView.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/VDS/Components/Buttons/ButtonBase.swift b/VDS/Components/Buttons/ButtonBase.swift index 255c6f64..cc096d41 100644 --- a/VDS/Components/Buttons/ButtonBase.swift +++ b/VDS/Components/Buttons/ButtonBase.swift @@ -102,6 +102,7 @@ open class ButtonBase: UIButton, ViewProtocol, UserInfoable, Clickable { //-------------------------------------------------- open func initialSetup() { if !initialSetupPerformed { + initialSetupPerformed = true backgroundColor = .clear translatesAutoresizingMaskIntoConstraints = false accessibilityCustomActions = [] diff --git a/VDS/Components/TextFields/TextArea/TextView.swift b/VDS/Components/TextFields/TextArea/TextView.swift index ea96ed6e..ffb355d1 100644 --- a/VDS/Components/TextFields/TextArea/TextView.swift +++ b/VDS/Components/TextFields/TextArea/TextView.swift @@ -94,6 +94,7 @@ open class TextView: UITextView, ViewProtocol { //-------------------------------------------------- open func initialSetup() { if !initialSetupPerformed { + initialSetupPerformed = true backgroundColor = .clear translatesAutoresizingMaskIntoConstraints = false accessibilityCustomActions = [] From 21ab644c16358f85f46a0e6996aff75a29b360c2 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 10:08:32 -0600 Subject: [PATCH 03/14] refactored for custom fonts Signed-off-by: Matt Bruce --- VDS/Fonts/Font.swift | 11 +++++++++-- VDS/Fonts/FontProtocol.swift | 3 ++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/VDS/Fonts/Font.swift b/VDS/Fonts/Font.swift index c5caaa32..6b875ad3 100644 --- a/VDS/Fonts/Font.swift +++ b/VDS/Fonts/Font.swift @@ -8,13 +8,14 @@ import Foundation /// Enum that is matched up for the Verizon fonts. -public enum Font: String, FontProtocol { +public enum Font: FontProtocol { case edsBold case edsRegular case dsLight case etxBold case etxRegular - + case custom(String) + public var fontName: String { switch self { case .edsBold: @@ -27,9 +28,15 @@ public enum Font: String, FontProtocol { return "VerizonNHGeTX-Bold" case .etxRegular: return "VerizonNHGeTX-Regular" + case .custom(let fontName): + return fontName } } + public static var allCases: [Font] { + [.edsBold, .edsRegular, .dsLight, .etxBold, .etxRegular] + } + /// File Extension for each of the Font enums. public var fontFileExtension: String { return "otf" diff --git a/VDS/Fonts/FontProtocol.swift b/VDS/Fonts/FontProtocol.swift index 9ee21939..fbca693b 100644 --- a/VDS/Fonts/FontProtocol.swift +++ b/VDS/Fonts/FontProtocol.swift @@ -9,9 +9,10 @@ import Foundation import UIKit /// Used in Classes that require Fonts -public protocol FontProtocol: CaseIterable, RawRepresentable, Hashable { +public protocol FontProtocol: Hashable { var fontFileExtension: String { get } var fontName: String { get } + static var allCases: [Self] { get } } extension FontProtocol { From 23f3f8b6bfe471b29ed8110785911f4e5ae4ae57 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 10:08:50 -0600 Subject: [PATCH 04/14] added a conversion of a UIFont to a TextStyle Signed-off-by: Matt Bruce --- VDS/Typography/Typogprahy+Styles.swift | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/VDS/Typography/Typogprahy+Styles.swift b/VDS/Typography/Typogprahy+Styles.swift index ec144617..0cd6e614 100644 --- a/VDS/Typography/Typogprahy+Styles.swift +++ b/VDS/Typography/Typogprahy+Styles.swift @@ -209,6 +209,24 @@ extension TextStyle { boldMicro ] } + + public static func convert(font: UIFont) -> TextStyle { + var found: TextStyle? + + for textStyle in allCases { + if font.fontName == textStyle.fontFace.fontName && + font.pointSize == textStyle.pointSize { + found = textStyle + break + } + } + + guard let found else { + return TextStyle(rawValue: "Custom", fontFace: .custom(font.fontName), pointSize: font.pointSize) + } + + return found + } } extension TextStyle { From 89a4c5d397e7df17355d5869c14ac03445e12d69 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 10:09:59 -0600 Subject: [PATCH 05/14] updated label with overrides for textColor and font Signed-off-by: Matt Bruce --- VDS/Components/Label/Label.swift | 35 +++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index c998c70b..0c89ae3f 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -131,32 +131,43 @@ open class Label: UILabel, ViewProtocol, UserInfoable { /// Line break mode for the label, default is set to word wrapping. open override var lineBreakMode: NSLineBreakMode { didSet { setNeedsUpdate() }} - - private var _text: String? - + /// Text that will be used in the label. - override public var text: String! { + override open var text: String! { get { super.text } set { - // When text is set, we may need to re-style it as attributedText - // with the correct paragraph style to achieve the desired line height. textSetMode = .text - attributes?.removeAll() styleText(newValue) } } ///AttributedText that will be used in the label. - override public var attributedText: NSAttributedString? { + override open var attributedText: NSAttributedString? { get { super.attributedText } set { - // When text is set, we may need to re-style it as attributedText - // with the correct paragraph style to achieve the desired line height. textSetMode = .attributedText styleAttributedText(newValue) } } + override open var font: UIFont! { + didSet { + if let font, initialSetupPerformed { + textStyle = TextStyle.convert(font: font) + } + setNeedsUpdate() + } + } + + override open var textColor: UIColor! { + didSet { + if let textColor, initialSetupPerformed { + textColorConfiguration = SurfaceColorConfiguration(textColor, textColor).eraseToAnyColorable() + } + setNeedsUpdate() + } + } + /// Whether the View is enabled or not. open override var isEnabled: Bool { didSet { setNeedsUpdate() } } @@ -175,13 +186,13 @@ open class Label: UILabel, ViewProtocol, UserInfoable { //-------------------------------------------------- open func initialSetup() { if !initialSetupPerformed { + initialSetupPerformed = true //register for ContentSizeChanges NotificationCenter .Publisher(center: .default, name: UIContentSizeCategory.didChangeNotification) .sink { [weak self] notification in self?.setNeedsUpdate() }.store(in: &subscribers) - backgroundColor = .clear numberOfLines = 0 lineBreakMode = .byWordWrapping @@ -307,7 +318,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable { return } - var mutableText = NSMutableAttributedString(attributedString: newValue) + let mutableText = NSMutableAttributedString(attributedString: newValue) applyAttributes(mutableText) From 473ab531e86e354b420811f2d8be77216aeb9f3e Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 12:34:07 -0600 Subject: [PATCH 06/14] fixed bug Signed-off-by: Matt Bruce --- VDS/Components/Label/Label.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index 0c89ae3f..60e88740 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -323,7 +323,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable { applyAttributes(mutableText) // Modify attributed text to match typography - super.attributedText = newValue + super.attributedText = mutableText } private func applyAttributes(_ mutableAttributedString: NSMutableAttributedString) { From fbdcdfc2774428db1efa330e18645280d1da84ab Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 12:34:23 -0600 Subject: [PATCH 07/14] refactored method Signed-off-by: Matt Bruce --- VDS/Typography/Typogprahy+Styles.swift | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/VDS/Typography/Typogprahy+Styles.swift b/VDS/Typography/Typogprahy+Styles.swift index 0cd6e614..0136d3c4 100644 --- a/VDS/Typography/Typogprahy+Styles.swift +++ b/VDS/Typography/Typogprahy+Styles.swift @@ -211,20 +211,9 @@ extension TextStyle { } public static func convert(font: UIFont) -> TextStyle { - var found: TextStyle? - - for textStyle in allCases { - if font.fontName == textStyle.fontFace.fontName && - font.pointSize == textStyle.pointSize { - found = textStyle - break - } + guard let found = allCases.first(where: { font.fontName == $0.fontFace.fontName && font.pointSize == $0.pointSize} ) else { + return TextStyle(rawValue: "Custom\(font.fontName)", fontFace: .custom(font), pointSize: font.pointSize) } - - guard let found else { - return TextStyle(rawValue: "Custom", fontFace: .custom(font.fontName), pointSize: font.pointSize) - } - return found } } From fd641a85cf5d2814f759322f9f33ec64c2f3ad37 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 8 Mar 2024 12:34:31 -0600 Subject: [PATCH 08/14] updated to handle custom fonts Signed-off-by: Matt Bruce --- VDS/Fonts/Font.swift | 22 +++++++++++++++++++--- VDS/Fonts/FontProtocol.swift | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/VDS/Fonts/Font.swift b/VDS/Fonts/Font.swift index 6b875ad3..f4ba798d 100644 --- a/VDS/Fonts/Font.swift +++ b/VDS/Fonts/Font.swift @@ -6,6 +6,7 @@ // import Foundation +import UIKit /// Enum that is matched up for the Verizon fonts. public enum Font: FontProtocol { @@ -14,7 +15,7 @@ public enum Font: FontProtocol { case dsLight case etxBold case etxRegular - case custom(String) + case custom(UIFont) public var fontName: String { switch self { @@ -28,8 +29,8 @@ public enum Font: FontProtocol { return "VerizonNHGeTX-Bold" case .etxRegular: return "VerizonNHGeTX-Regular" - case .custom(let fontName): - return fontName + case .custom(let font): + return font.fontName } } @@ -41,4 +42,19 @@ public enum Font: FontProtocol { public var fontFileExtension: String { return "otf" } + + /// Returns a UIFont for the fontName and size given. + /// - Parameters: + /// - size: Size of the font + /// - Returns: UIFont for the fontName and Size. + public func font(ofSize size: CGFloat) -> UIFont{ + DispatchQueue.once(block: { self.register() }) + switch self { + case .custom(let font): + return font + default: + guard let found = UIFont(name: self.fontName, size: size) else { return .systemFont(ofSize: size) } + return found + } + } } diff --git a/VDS/Fonts/FontProtocol.swift b/VDS/Fonts/FontProtocol.swift index fbca693b..df6ac6a3 100644 --- a/VDS/Fonts/FontProtocol.swift +++ b/VDS/Fonts/FontProtocol.swift @@ -9,7 +9,7 @@ import Foundation import UIKit /// Used in Classes that require Fonts -public protocol FontProtocol: Hashable { +public protocol FontProtocol { var fontFileExtension: String { get } var fontName: String { get } static var allCases: [Self] { get } From 466dbb7c6a2d697020128a0b527931d62e079075 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 12:47:16 -0500 Subject: [PATCH 09/14] update for TitleLockup for label compression/hugging Signed-off-by: Matt Bruce --- VDS/Components/TitleLockup/TitleLockup.swift | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/VDS/Components/TitleLockup/TitleLockup.swift b/VDS/Components/TitleLockup/TitleLockup.swift index e11b674d..3802b529 100644 --- a/VDS/Components/TitleLockup/TitleLockup.swift +++ b/VDS/Components/TitleLockup/TitleLockup.swift @@ -68,6 +68,7 @@ open class TitleLockup: View { /// Label used to render the eyebrow model. open var eyebrowLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.setContentHuggingPriority(.required, for: .vertical) } /// Model used in rendering the eyebrow label. @@ -77,6 +78,7 @@ open class TitleLockup: View { /// Label used to render the title model. open var titleLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.setContentHuggingPriority(.required, for: .vertical) $0.accessibilityTraits.insert([.header]) } @@ -87,6 +89,7 @@ open class TitleLockup: View { /// Label used to render the subtitle model. open var subTitleLabel = Label().with { $0.setContentCompressionResistancePriority(.required, for: .vertical) + $0.setContentHuggingPriority(.required, for: .vertical) } /// Model used in rendering the subtitle label. @@ -380,7 +383,7 @@ open class TitleLockup: View { } //pin the last view to the bottom of this view - previousView?.pinBottom(0, .defaultHigh) + previousView?.pinBottom(0) //debugging for borders eyebrowLabel.debugBorder(show: hasDebugBorder, color: .green) From 4733a3a00c000300e6056d87fb0ec16d2cce3bba Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 12:47:38 -0500 Subject: [PATCH 10/14] refactored to not use KVO, but a publisher KVO Signed-off-by: Matt Bruce --- VDS/Classes/SelfSizingCollectionView.swift | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/VDS/Classes/SelfSizingCollectionView.swift b/VDS/Classes/SelfSizingCollectionView.swift index c50082c4..6f37308c 100644 --- a/VDS/Classes/SelfSizingCollectionView.swift +++ b/VDS/Classes/SelfSizingCollectionView.swift @@ -34,7 +34,6 @@ public final class SelfSizingCollectionView: UICollectionView { //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- - private var contentSizeObservation: NSKeyValueObservation? private var collectionViewHeight: NSLayoutConstraint? private var anyCancellable: AnyCancellable? @@ -45,7 +44,6 @@ public final class SelfSizingCollectionView: UICollectionView { /// The natural size for the receiving view, considering only properties of the view itself. public override var intrinsicContentSize: CGSize { let contentSize = self.contentSize - //print(#function, contentSize) return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height) } @@ -68,17 +66,21 @@ public final class SelfSizingCollectionView: UICollectionView { setContentHuggingPriority(.required, for: .vertical) setContentCompressionResistancePriority(.required, for: .vertical) collectionViewHeight = heightAnchor.constraint(equalToConstant: 0).activate() - - // 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() - if let height = change.newValue?.height { - self?.collectionViewHeight?.constant = height + + anyCancellable = self.publisher(for: \.contentSize, options: [.old, .new]) + .scan((old: CGSize.zero, new: CGSize.zero)) { accumulator, newValue in + // accumulator.old contains the old contentSize value + // accumulator.new contains the new contentSize value before the current update + // newValue is the current update to contentSize + return (old: accumulator.new, new: newValue) + } + .sink { [weak self] compare in + if compare.old != compare.new { + print("Old contentSize: \(compare.old), New contentSize: \(compare.new)") + self?.invalidateIntrinsicContentSize() + self?.collectionViewHeight?.constant = compare.new.height } } - } } } From 73c7e23b99bb099835323b8ea463a76b0acc71c7 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 12:56:14 -0500 Subject: [PATCH 11/14] removed print Signed-off-by: Matt Bruce --- VDS/Classes/SelfSizingCollectionView.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/VDS/Classes/SelfSizingCollectionView.swift b/VDS/Classes/SelfSizingCollectionView.swift index 6f37308c..d8656490 100644 --- a/VDS/Classes/SelfSizingCollectionView.swift +++ b/VDS/Classes/SelfSizingCollectionView.swift @@ -76,7 +76,6 @@ public final class SelfSizingCollectionView: UICollectionView { } .sink { [weak self] compare in if compare.old != compare.new { - print("Old contentSize: \(compare.old), New contentSize: \(compare.new)") self?.invalidateIntrinsicContentSize() self?.collectionViewHeight?.constant = compare.new.height } From 6aa09da464b7693edf207920193f378b2287a355 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 13:51:19 -0500 Subject: [PATCH 12/14] refactored to have a public contentSize publisher Signed-off-by: Matt Bruce --- VDS/Classes/SelfSizingCollectionView.swift | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/VDS/Classes/SelfSizingCollectionView.swift b/VDS/Classes/SelfSizingCollectionView.swift index d8656490..6f4de7d0 100644 --- a/VDS/Classes/SelfSizingCollectionView.swift +++ b/VDS/Classes/SelfSizingCollectionView.swift @@ -36,7 +36,15 @@ public final class SelfSizingCollectionView: UICollectionView { //-------------------------------------------------- private var collectionViewHeight: NSLayoutConstraint? private var anyCancellable: AnyCancellable? - + private var contentSizeSubject = CurrentValueSubject(.zero) + + //-------------------------------------------------- + // MARK: - Public Properties + //-------------------------------------------------- + public var contentSizePublisher: AnyPublisher { + contentSizeSubject.eraseToAnyPublisher() + } + //-------------------------------------------------- // MARK: - Overrides //-------------------------------------------------- @@ -67,17 +75,13 @@ public final class SelfSizingCollectionView: UICollectionView { setContentCompressionResistancePriority(.required, for: .vertical) collectionViewHeight = heightAnchor.constraint(equalToConstant: 0).activate() - anyCancellable = self.publisher(for: \.contentSize, options: [.old, .new]) - .scan((old: CGSize.zero, new: CGSize.zero)) { accumulator, newValue in - // accumulator.old contains the old contentSize value - // accumulator.new contains the new contentSize value before the current update - // newValue is the current update to contentSize - return (old: accumulator.new, new: newValue) - } + anyCancellable = self.publisher(for: \.contentSize, options: [.new]) .sink { [weak self] compare in - if compare.old != compare.new { - self?.invalidateIntrinsicContentSize() - self?.collectionViewHeight?.constant = compare.new.height + guard let self else { return } + if compare.height != self.collectionViewHeight?.constant { + self.invalidateIntrinsicContentSize() + self.collectionViewHeight?.constant = compare.height + self.contentSizeSubject.send(compare) } } } From 59b72835c08b05b2c2012b9f14adc4168ec94a9a Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 13:51:32 -0500 Subject: [PATCH 13/14] include new contentSizePublisher Signed-off-by: Matt Bruce --- VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift index 7d506961..a51371c2 100644 --- a/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift +++ b/VDS/Components/Buttons/ButtonGroup/ButtonGroup.swift @@ -9,6 +9,7 @@ import Foundation import UIKit import VDSColorTokens import VDSFormControlsTokens +import Combine /// A button group contains combinations of related CTAs including ``Button``, ``TextLink``, and ``TextLinkCaret``. This group component controls a combination's orientation, spacing, size and allowable size pairings. @objc(VDSButtonGroup) @@ -98,6 +99,8 @@ open class ButtonGroup: View { buttons.forEach { $0.surface = surface } } } + + open var contentSizePublisher: AnyPublisher { collectionView.contentSizePublisher } //-------------------------------------------------- // MARK: - Private Properties @@ -108,6 +111,7 @@ open class ButtonGroup: View { $0.delegate = self } + /// CollectionView that renders the array of buttonBase obects. fileprivate lazy var collectionView: SelfSizingCollectionView = { return SelfSizingCollectionView(frame: .zero, collectionViewLayout: positionLayout).with { From 1fa8f485f8a92e5dc9ba8bf8e8eb5fb52ce092d2 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Mon, 11 Mar 2024 15:43:55 -0500 Subject: [PATCH 14/14] updated constraint to defaultHigh Signed-off-by: Matt Bruce --- VDS/Classes/SelfSizingCollectionView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VDS/Classes/SelfSizingCollectionView.swift b/VDS/Classes/SelfSizingCollectionView.swift index 6f4de7d0..ad5d5661 100644 --- a/VDS/Classes/SelfSizingCollectionView.swift +++ b/VDS/Classes/SelfSizingCollectionView.swift @@ -73,7 +73,7 @@ public final class SelfSizingCollectionView: UICollectionView { //ensure autoLayout uses intrinsic height setContentHuggingPriority(.required, for: .vertical) setContentCompressionResistancePriority(.required, for: .vertical) - collectionViewHeight = heightAnchor.constraint(equalToConstant: 0).activate() + collectionViewHeight = height(constant: 0, priority: .defaultHigh) anyCancellable = self.publisher(for: \.contentSize, options: [.new]) .sink { [weak self] compare in