Skip to content
Programmatic creation of NSAttributedString doesn't have to be a pain
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Carthage
Tribute.playground update color property by using #colorLiteral in playground Oct 17, 2016
Tribute.xcodeproj
Tribute
TributeTests
docs Adjust image size Dec 6, 2015
fastlane Test tribute scheme Dec 10, 2015
.gitignore
.travis.yml
Cartfile Initial commit Dec 1, 2015
Cartfile.private Initial commit Dec 1, 2015
Cartfile.resolved
Gemfile
Gemfile.lock
LICENSE.md
README.md
Tribute.podspec

README.md

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

You can’t perform that action at this time.