Skip to content

Instantly share code, notes, and snippets.

@lionhylra
Created January 22, 2020 06:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lionhylra/4bade5433ecbdf255e8da63a1f793e24 to your computer and use it in GitHub Desktop.
Save lionhylra/4bade5433ecbdf255e8da63a1f793e24 to your computer and use it in GitHub Desktop.
import UIKit
/* Example of how to use it:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
let style = NSAttributedStringStyle(font: .preferredFont(forTextStyle: .body))
label.attributedText = .compose(
style: style,
"""
Please go to \(urlString: "https://google.com" ) for more details. \(systemImage: "globe")
Also you can go to our \(link: "Website", urlString: "https://google.com").
This is another line.
"""
)
textView.attributedText = .compose(
style: style,
"""
Please go to \(urlString: "https://google.com" ) for more details. \(systemImage: "globe")
Also you can go to our \(link: "Website", urlString: "https://google.com").
This is another line.
"""
)
}
}
*/
struct NSAttributedStringLiteral: ExpressibleByStringLiteral {
let value: NSAttributedString
init(stringLiteral value: String) {
self.value = NSAttributedString(string: value)
}
}
extension NSAttributedStringLiteral: ExpressibleByStringInterpolation {
init(stringInterpolation: StringInterpolation) {
self.value = stringInterpolation.output
}
}
extension NSAttributedStringLiteral {
struct StringInterpolation: StringInterpolationProtocol {
var output = NSMutableAttributedString()
init(literalCapacity: Int, interpolationCount: Int) {
// DO NOTHING
// this initializer is required, and can be used as a performance optimization
}
mutating func appendLiteral(_ literal: String) {
output.append(NSAttributedString(string: literal))
}
mutating func appendInterpolation(link label: String? = nil, url: URL) {
output.append(NSAttributedString(string: label ?? url.absoluteString, attributes: [.link: url]))
}
mutating func appendInterpolation(link label: String? = nil, urlString: String) {
assert(URL(string: urlString) != nil)
output.append(NSAttributedString(string: label ?? urlString, attributes: [.link: urlString]))
}
mutating func appendInterpolation(image: UIImage?, size: CGSize? = nil) {
let attachment = NSTextAttachment()
attachment.image = image
if let size = size {
attachment.bounds.size = size
}
output.append(NSAttributedString(attachment: attachment))
}
@available(iOS 13.0, *)
mutating func appendInterpolation(systemImage name: String, tintColor: UIColor? = nil) {
var image = UIImage(systemName: name)
if let tintColor = tintColor {
image = image?.withTintColor(tintColor)
}
appendInterpolation(image: image)
}
}
}
struct NSAttributedStringStyle {
static let `default` = NSAttributedStringStyle()
let font: UIFont?
let foregroundColor: UIColor?
let alignment: NSTextAlignment?
let lineSpacing: CGFloat?
let paragraphSpacing: CGFloat?
init(font: UIFont? = nil, foregroundColor: UIColor? = nil, alignment: NSTextAlignment? = nil, lineSpacing: CGFloat? = nil, paragraphSpacing: CGFloat? = nil) {
self.font = font
self.foregroundColor = foregroundColor
self.alignment = alignment
self.lineSpacing = lineSpacing
self.paragraphSpacing = paragraphSpacing
}
func attributes() -> [NSAttributedString.Key: Any] {
var attributes: [NSAttributedString.Key: Any] = [:]
attributes[.font] = font
attributes[.foregroundColor] = foregroundColor
let paragraphStyle = NSMutableParagraphStyle()
if let alignment = alignment {
paragraphStyle.alignment = alignment
}
if let lineSpacing = lineSpacing {
paragraphStyle.lineSpacing = lineSpacing
}
if let paragraphSpacing = paragraphSpacing {
paragraphStyle.paragraphSpacing = paragraphSpacing
}
attributes[.paragraphStyle] = paragraphStyle
return attributes
}
}
extension NSAttributedString {
static func compose(style: NSAttributedStringStyle = .default, _ literal: NSAttributedStringLiteral) -> NSAttributedString {
let mutableAttributedString = NSMutableAttributedString(attributedString: literal.value)
let range = NSRange(location: 0, length: mutableAttributedString.length)
mutableAttributedString.addAttributes(style.attributes(), range: range)
return mutableAttributedString
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment