Skip to content
/ Tribute Public

Programmatic creation of NSAttributedString doesn't have to be a pain

License

Notifications You must be signed in to change notification settings

zats/Tribute

Repository files navigation

Tribute Build Status

let string = NSMutableAttributedString().add("Hello ") {
    $0.font = .systemFontOfSize(20)
    $0.color = .redColor()
    $0.underline = .StyleSingle
}.add("world ") {
    $0.stroke = .Filled(width: 2)
    $0.strokeColor = .orangeColor()
}.add("of Swift "){
    $0.font = .systemFontOfSize(12)
    $0.underline = nil
    $0.URL = NSURL(string: "http://swift.org")!
}.add(UIImage(named: "swift")!)

Not bad comparing to

let string2 = NSMutableAttributedString()
string2.appendAttributedString(NSAttributedString(string: "Hello ", attributes: [
    NSFontAttributeName: UIFont.systemFontOfSize(20),
    NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue,
    NSForegroundColorAttributeName: UIColor.redColor()
]))
string2.appendAttributedString(NSAttributedString(string: "world ", attributes: [
    NSFontAttributeName: UIFont.systemFontOfSize(20),
    NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue,
    NSForegroundColorAttributeName: UIColor.redColor(),
    NSStrokeColorAttributeName: UIColor.orangeColor(),
    NSStrokeWidthAttributeName: -2
]))
string2.appendAttributedString(NSAttributedString(string: "of Swift ", attributes: [
    NSFontAttributeName: UIFont.systemFontOfSize(12),
    NSForegroundColorAttributeName: UIColor.redColor(),
    NSStrokeColorAttributeName: UIColor.orangeColor(),
    NSStrokeWidthAttributeName: -2
]))
let attachment = NSTextAttachment()
attachment.image = UIImage(named: "swift")
string2.appendAttributedString(NSAttributedString(attachment: attachment))

Design Goals

  1. Word processor logic: appending a string should inherit last attributes.
  2. Allow for easy customization of common properties, including toggle bold or change the font size.
  3. Flatten paragraph style and attributes, no more 5 lines of code if all you wanted is to change text alignment.
  4. Replace weird attributes with more reasonable versions (for example Attribute.Stroke vs NSStrokeWidthAttributeName).
  5. Minimal overhead: produce only required attributes.
  6. Have an attributed string ready to use every time you leave the configuration block.
  7. Replace string constants with strongly typed enums where possible.

Notes

Playground

Playgrounds do not always render NSAttributesString correctly (font variations and attachments are few of the problematic I noticed).

Workaround: Use a UILabel as a live view instead: XCPlaygroundPage.currentPage.liveView = label.

Font variations

Not all fonts have both italic and bold variations

Workaround: Use obliqueness property as a poor man italic, and expansion as a bold respectively.

Closure with one statement

When the configuration closure includes only one statement, compiler gets confused

Workaround: Specify closure type explicitly like so

string.add("text") { (inout a: Attributes) in
    a.color = .redColor()
}

If you know a better way, please open a PR, I'd love to learn from it!

Roadmap

  • Objective-C compatibility
  • Moar attributes (PRs are welcome)

This is just a tribute

About

Programmatic creation of NSAttributedString doesn't have to be a pain

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •