diff --git a/VDS/Components/Label/Attributes/ActionLabelAttribute.swift b/VDS/Components/Label/Attributes/ActionLabelAttribute.swift index acd28f91..6d7a1034 100644 --- a/VDS/Components/Label/Attributes/ActionLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/ActionLabelAttribute.swift @@ -56,6 +56,8 @@ public struct ActionLabelAttribute: ActionLabelAttributeModel { } public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } + if(shouldUnderline){ UnderlineLabelAttribute(location: location, length: length).setAttribute(on: attributedString) } diff --git a/VDS/Components/Label/Attributes/AttachmentLabelAttributeModel.swift b/VDS/Components/Label/Attributes/AttachmentLabelAttributeModel.swift index 5de6f4b2..c4f9bd79 100644 --- a/VDS/Components/Label/Attributes/AttachmentLabelAttributeModel.swift +++ b/VDS/Components/Label/Attributes/AttachmentLabelAttributeModel.swift @@ -14,6 +14,8 @@ public protocol AttachmentLabelAttributeModel: LabelAttributeModel { extension AttachmentLabelAttributeModel { public func setAttribute(on attributedString: NSMutableAttributedString) { + guard isValidRange(on: attributedString) else { return } + do { let mutableString = NSMutableAttributedString() let attachment = try getAttachment() diff --git a/VDS/Components/Label/Attributes/LabelAttributeModel.swift b/VDS/Components/Label/Attributes/LabelAttributeModel.swift index ac43472f..01dfec08 100644 --- a/VDS/Components/Label/Attributes/LabelAttributeModel.swift +++ b/VDS/Components/Label/Attributes/LabelAttributeModel.swift @@ -31,11 +31,21 @@ extension LabelAttributeModel { } public func isValidRange(on attributedString: NSMutableAttributedString) -> Bool { - range.location + range.length <= attributedString.string.count + attributedString.isValid(range: range) + } +} + +public extension String { + func isValid(range: NSRange) -> Bool { + range.location >= 0 && range.length > 0 && range.location + range.length <= count } } public extension NSAttributedString { + func isValid(range: NSRange) -> Bool { + range.location >= 0 && range.length > 0 && range.location + range.length <= length + } + func createAttributeModels() -> [(any LabelAttributeModel)] { var attributes: [any VDS.LabelAttributeModel] = [] enumerateAttributes(in: NSMakeRange(0, length)) { attributeMap, range, stop in @@ -61,6 +71,7 @@ public extension NSAttributedString { extension NSMutableAttributedString { public func apply(attribute: any LabelAttributeModel) { + guard isValid(range: attribute.range) else { return } attribute.setAttribute(on: self) } diff --git a/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift b/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift index 914a8783..bd02cf87 100644 --- a/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift +++ b/VDS/Components/Label/Attributes/TooltipLabelAttribute.swift @@ -24,7 +24,9 @@ public class TooltipLabelAttribute: ActionLabelAttributeModel, TooltipLaunchable public var presenter: UIView? public func setAttribute(on attributedString: NSMutableAttributedString) { - //update the location + guard isValidRange(on: attributedString) else { return } + + //update the location location = attributedString.string.count - 1 //set the default color off surface for text diff --git a/VDS/Components/Label/Label.swift b/VDS/Components/Label/Label.swift index 955d9604..c0edef0b 100644 --- a/VDS/Components/Label/Label.swift +++ b/VDS/Components/Label/Label.swift @@ -344,7 +344,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable { for attribute in attributes { //see if the attribute is Actionable - if let actionable = attribute as? any ActionLabelAttributeModel{ + if let actionable = attribute as? any ActionLabelAttributeModel, mutableAttributedString.isValid(range: actionable.range) { //create a accessibleAction let customAccessibilityAction = customAccessibilityAction(text: mutableAttributedString.string, range: actionable.range, accessibleText: actionable.accessibleText) @@ -379,7 +379,7 @@ open class Label: UILabel, ViewProtocol, UserInfoable { guard let text = text, let attributedText else { return nil } - let actionText = accessibleText ?? NSString(string:text).substring(with: range) + let actionText = accessibleText ?? (text.isValid(range: range) ? NSString(string:text).substring(with: range) : text) // Calculate the frame of the substring let layoutManager = NSLayoutManager()