Skip to content

Instantly share code, notes, and snippets.

@josippetric
Last active March 28, 2023 07:33
Show Gist options
  • Select an option

  • Save josippetric/a7322fe4a6bd29c84384fc8217c55198 to your computer and use it in GitHub Desktop.

Select an option

Save josippetric/a7322fe4a6bd29c84384fc8217c55198 to your computer and use it in GitHub Desktop.
Swift Attributed String Construction Helpers
import UIKit
public enum AttributeConstructor {
public enum Attribute {
case lineHeight(CGFloat)
case lineHeightMultiple(CGFloat)
case alignment(NSTextAlignment)
case font(UIFont)
case kern(CGFloat)
case color(UIColor)
case baselineOffset(CGFloat)
case lineBreakMode(NSLineBreakMode)
case underline
case strikeThrough(UIColor)
}
public static func construct(_ attributes: [Attribute]) -> [NSAttributedString.Key: Any] {
let paragraphStyle = NSMutableParagraphStyle()
var attributesDic = [NSAttributedString.Key: Any]()
attributes.forEach {
switch $0 {
case let .lineHeight(value):
paragraphStyle.minimumLineHeight = value
case let .lineHeightMultiple(value):
paragraphStyle.lineHeightMultiple = value
case let .alignment(alignment):
paragraphStyle.alignment = alignment
case let .font(font):
attributesDic[.font] = font
case let .kern(kern):
attributesDic[.kern] = kern
case let .color(color):
attributesDic[.foregroundColor] = color
case let .baselineOffset(baselineOffset):
attributesDic[.baselineOffset] = baselineOffset
case let .lineBreakMode(lineBreakMode):
paragraphStyle.lineBreakMode = lineBreakMode
case .underline:
attributesDic[.underlineStyle] = NSUnderlineStyle.single.rawValue
case let .strikeThrough(color):
attributesDic[.strikethroughColor] = color
attributesDic[.strikethroughStyle] = NSUnderlineStyle.single.rawValue
}
}
attributesDic[.paragraphStyle] = paragraphStyle
return attributesDic
}
}
extension NSAttributedString {
convenience init(string: String, attributes: [AttributeConstructor.Attribute]) {
let attributes = AttributeConstructor.construct(attributes)
self.init(string: string, attributes: attributes)
}
public func highlight(
substring: String,
attributes: AttributeConstructor.Attribute...
) -> NSAttributedString {
let resultString = NSMutableAttributedString(attributedString: self)
let nsText = string as NSString
let range = nsText.range(of: substring)
let attributes = AttributeConstructor.construct(attributes)
resultString.addAttributes(attributes, range: range)
return resultString
}
public var mutable: NSMutableAttributedString {
return .init(attributedString: self)
}
}
extension NSMutableAttributedString {
public func addAttributes(_ attrs: AttributeConstructor.Attribute..., range: NSRange) {
let attributes = AttributeConstructor.construct(attrs)
addAttributes(attributes, range: range)
}
}
extension String {
public typealias Attribute = AttributeConstructor.Attribute
public func withAttributes(_ attributes: Attribute...) -> NSAttributedString {
let attributes = AttributeConstructor.construct(attributes)
return NSAttributedString(string: self, attributes: attributes)
}
public func withAttributes(_ attributes: [Attribute]) -> NSAttributedString {
let attributes = AttributeConstructor.construct(attributes)
return NSAttributedString(string: self, attributes: attributes)
}
}
// Usage example
"some string".withAttributes(
.font(AppFonts.regular.fontWithSize(12.0)),
.color(UIColor.blue),
.kern(0.4),
.lineHeight(18)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment