flohei flohei - 11 months ago 83
Swift Question

NSAttributedString with UIFontWeightTraits

I'm trying to generate a

that has basically just the default font, is italic and a different text color. Easy enough, so far.

Now I want different substrings of this entire string to additionally be bold. It should basically look like this:

from John Smith on 25.08. at 8:00

(Just in a different color.)

It looks like I'm getting the dictionary wrong, that I pass into the
function. From the documentation, I understood that this dictionary should look like this:

[UIFontWeightTrait: NSNumber(double: Double(UIFontWeightBold))]

But this does not seem to work. All I end up with is the italic version of the string. I'm clearly getting something wrong here. Any idea?

Update: Adding simple example

// Preparation
let rawString = "from John Smith on 25.08. at 8:00"
let attributedString = NSMutableAttributedString(string: rawString)
let nameRange = (rawString as NSString).rangeOfString("John Smith")
let italicFont = UIFont.italicSystemFontOfSize(14)

// Make entire string italic: works!
attributedString.addAttributes([NSFontAttributeName : italicFont], range: NSMakeRange(0, 33))
// Make the name string additionally bold: doesn't work!
[UIFontWeightTrait: NSNumber(double: Double(UIFontWeightBold))]], range: nameRange)

// Show it on the label
attributedStringLabel.attributedText = attributedString


Answer Source

UIFontDescriptorTraitsAttribute is not a recognized key in the NSAttributedString attributes dictionary, so having obtained the traits you need to reconstruct a UIFont and use the NSFontAttributeName key.

    //prepare the fonts. we derive the bold-italic font from the italic font
    let italicFont = UIFont.italicSystemFontOfSize(14)
    let italicDesc = italicFont.fontDescriptor()
    let italicTraits  = italicDesc.symbolicTraits.rawValue
    let boldTrait = UIFontDescriptorSymbolicTraits.TraitBold.rawValue
    let boldItalicTraits = UIFontDescriptorSymbolicTraits(rawValue:italicTraits | boldTrait)
    let boldItalicDescriptor = italicDesc.fontDescriptorWithSymbolicTraits(boldItalicTraits)
    let boldItalicFont = UIFont(descriptor: boldItalicDescriptor, size: 0.0)

    //prepare the string
    let rawString = "from John Smith on 25.08. at 8:00"
    let attributedString = NSMutableAttributedString(string: rawString)

    let fullRange = NSMakeRange(0, 33)
    let nameRange = (rawString as NSString).rangeOfString("John Smith")

    attributedString.addAttributes([NSFontAttributeName:italicFont], range: fullRange)
    attributedString.addAttributes([NSFontAttributeName:boldItalicFont], range: nameRange)

see also:NSAttributedString: Setting FontAttributes doesn't change font