Skip to content

Instantly share code, notes, and snippets.

@joshuawright11
Last active May 4, 2021 00:55
Show Gist options
  • Save joshuawright11/05b3f8f220f544220a2dc0f1ae5384e3 to your computer and use it in GitHub Desktop.
Save joshuawright11/05b3f8f220f544220a2dc0f1ae5384e3 to your computer and use it in GitHub Desktop.
Swift attributed strings with @resultBuilder
import UIKit
public protocol AttributedStringConvertible {
var attributedString: NSMutableAttributedString { get }
}
extension String: AttributedStringConvertible {
public var attributedString: NSMutableAttributedString {
NSMutableAttributedString(string: self)
}
}
extension NSMutableAttributedString: AttributedStringConvertible {
public var attributedString: NSMutableAttributedString {
self
}
}
extension AttributedStringConvertible {
public func font(_ font: UIFont) -> NSMutableAttributedString {
let attr = attributedString
attr.addAttribute(.font, value: font, range: NSRange(location: 0, length: attr.length))
return attr
}
public func color(_ color: UIColor) -> NSMutableAttributedString {
let attr = attributedString
attr.addAttribute(.foregroundColor, value: color, range: NSRange(location: 0, length: attr.length))
return attr
}
public static func attributed(@AttributedStringBuilder _ data: () -> NSMutableAttributedString) -> NSMutableAttributedString {
data()
}
}
@resultBuilder
public struct AttributedStringBuilder {
public static func buildBlock(_ components: AttributedStringConvertible...) -> NSMutableAttributedString {
components.map(\.attributedString).joined()
}
public static func buildEither(first component: AttributedStringConvertible) -> AttributedStringConvertible {
component
}
public static func buildEither(second component: AttributedStringConvertible) -> AttributedStringConvertible {
component
}
public static func buildOptional(_ component: AttributedStringConvertible?) -> AttributedStringConvertible {
component ?? ""
}
public static func buildArray(_ components: [AttributedStringConvertible]) -> AttributedStringConvertible {
components.map(\.attributedString).joined()
}
}
extension Array where Element == NSMutableAttributedString {
fileprivate func joined() -> NSMutableAttributedString {
reduce(NSMutableAttributedString()) {
$0.append($1)
return $0
}
}
}
@joshuawright11
Copy link
Author

Usage

someLabel.attributedText = String.attributed {
    "up to "
    "$543,000".font(.bold14).color(.primary6)
    " lifetime impact"
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment