Swapnil Dhanwal
Swapnil Dhanwal

Reputation: 399

Unable to add attributed string with font Avenir Next Condensed [Swift 3]

    let s = NSAttributedString(string: "Percentage", attributes: [NSFontAttributeName : UIFont(name : "Avenir Next Condensed", size : 20), NSUnderlineStyleAttributeName : NSUnderlineStyle.byWord])
    textView.attributedText = s

I get the following error for the above code: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue _isDefaultFace]: unrecognized selector sent to instance 0x608000046930'

If I change the NSFontAttributeName to UIFont.boldSystemFont(ofSize: 20), I can see bold text. Also on adding NSUnderlineStyleAttributeName, I don't see any text at all. How can I fix this?

Upvotes: 0

Views: 3619

Answers (1)

OOPer
OOPer

Reputation: 47886

Two things:

  • You cannot pass Optional value to where non-Null id value is needed.

The attributes: parameter is internally converted to NSDictionary, where its values cannot be nil. But UIFont.init(name:size:) is a faileable initializer, so its return type is Optional. In Swift 3.0.0, Swift generates an instance of type _SwiftValue when converting it to non-Null id. And store it in the attributes. Which is completely useless in the Objective-C side. (This happens even if the actual value is not nil.)

(Swift 3.0.1 improved some parts of this situation.)

  • You cannot pass Swift enums to where id value is needed.

NSUnderlineStyle.byWord is a Swift enum. In Swift 3,Swift generates an instance of type _SwiftValue when converting it to id.

(Swift 3.0.1 has not improved about this situation.)

To fix the two above things, you need to write something like this:

if let font = UIFont(name: "Avenir Next Condensed", size: 20) {
    let s = NSAttributedString(string: "Percentage", attributes: [NSFontAttributeName: font, NSUnderlineStyleAttributeName: NSUnderlineStyle.byWord.rawValue])
    textView.attributedText = s
}

Upvotes: 2

Related Questions