Setting Nsunderlinestyle Causes Unrecogognized Selector Exception

Setting NSUnderlineStyle causes unrecogognized selector exception

Change line:

let attributes = [NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle]

to:

let attributes = [NSUnderlineStyleAttributeName:NSUnderlineStyle.styleSingle.rawValue]

Swift 4.2: [Swift._EmptyArrayStorage _getValue:forType:]: unrecognized selector

I just found out what was wrong in the code.

So, because of the compiler error "'none' is unavailable: use [] to construct an empty option set", I replaced the NSUnderlineStyle.none.rawValue with [] ‍♂️ And that's not the right case because it was using the rawValue, not the type none.

So, the fix is using 0.

Wrong: mutableAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: [], range: range)

Right: mutableAttributedString.addAttribute(NSAttributedString.Key.underlineStyle, value: 0, range: range)

App crashed when invoking NSAttributedString.boundingRectWithSize

The value for the key - NSAttributedString.Key.underlineStyle should contain the rawValue at the end, like so - NSUnderlineStyle.single.rawValue.

You can see the code below:

let attributedStr = NSMutableAttributedString(string: "Some description.")

let underlineText = NSAttributedString(string: "Click Here", attributes: [
NSAttributedString.Key.foregroundColor : UIColor.blue,
NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14.0)])

attributedStr.append(underlineText)

NSAttributedString with strikethrough

First, the value for NSStrikethroughStyleAttributeName must be an NSNumber, not a simple integer. Second, I think you have to include NSUnderlineStyleSingle:

...:[NSDictionary dictionaryWithObjectsAndKeys:
...,
[NSNumber numberWithInteger:NSUnderlinePatternSolid | NSUnderlineStyleSingle],
NSStrikethroughStyleAttributeName,
nil]...

Attributed text with TextView causing a crash

please add font name and size

func getAttributedTermsAndServicesText() -> NSAttributedString {
let text = StringConstants.RegisterConstants.termsOfUseLabelText
let attributedString = NSMutableAttributedString(string: text)
let termsRange = attributedString.mutableString.range(of: StringConstants.CommonConstants.termsOfUse)

attributedString.addAttribute(NSAttributedStringKey.link, value: WebViewLinkType.termsOfUse.getLink(), range: termsRange)
attributedString.addAttribute(NSAttributedStringKey.underlineStyle, value: NSUnderlineStyle.styleSingle.rawValue, range: termsRange)

let privacyRange = attributedString.mutableString.range(of: StringConstants.CommonConstants.privacyStatement)
attributedString.addAttribute(NSAttributedStringKey.link, value: WebViewLinkType.privacyStatement.getLink(), range: privacyRange)
attributedString.addAttribute(NSAttributedStringKey.underlineStyle, value: NSUnderlineStyle.styleSingle.rawValue, range: privacyRange)

print(attributedString.mutableString)
return attributedString
}

How to get NSAttributedString's underline style attribute to work?

NSUnderlineStyle Is Not the Proper Type

Precisely, but somewhat unhelpfully, the documentation explains that the underlineStyle attribute key takes an attribute value of an "NSNumber containing an integer."

The value of this attribute is an NSNumber object containing an
integer. This value indicates whether the text is underlined and
corresponds to one of the constants described in NSUnderlineStyle. The
default value for this attribute is styleNone.

Many readers are drawn to NSUnderlineStyle, click on it, and find an enum-like list of styles: single, thick, patternDash, double, etc. That all seems like a good Swifty solution. The reader intuits that this enum must be the way to specify the attribute value, and types the sort of code shown in the question, above.


The rawValue Property of NSUnderlineStyle Provides The Proper Type

NSUnderlineStyle is not an enum. It is a struct that conforms to the OptionSet protocol. The OptionSet protocol is a convenient, Swifty way of setting the bits of an integer, with each bit representing a binary state. The NSUnderlineStyle struct is a wrapper around that integer. Its enum-like styles actually are static vars on the struct, each of which returns an instance of NSUnderlineStyle with the embedded integer, with just one of the bits flipped to correspond to the desired style.

NSAttributedString's dictionary of attributes takes literally anything as a value, so it happily accepts instances of NSUnderlineStyle. But TextKit, the engine that makes UITextView and UILabel work, doesn't know what to do with an NSUnderlineStyle instance. When TextKit tries to render an underlineStyle attribute, it wants an integer so that it can determine the correct style by checking the bits of the integer.

Fortunately, there is an easy way to get at that integer. The rawValue property of NSUnderlineStyle vends it. Thus, a properly working version of our code snippet is as follows:

let string = NSMutableAttributedString(string: "This is my string.")

string.addAttributes([.underlineStyle : NSUnderlineStyle.single.rawValue],
range: NSRange(location: 5, length: 2))

The only difference between this code and the code in the question is the addition of ".rawValue" to "NSUnderlineStyle.single". And, "is" is underlined.

As a side note, the type vended by the rawValue property is an Int, not an NSNumber. The documentation's reference to the attribute value being an NSNumber can be confusing. Under the hood, to interoperate with ObjC, NSAttributedString wraps the Int inside an NSNumber. There is no need for (or benefit to?) explicitly wrapping the Int in NSNumber.


Use the OptionSet union Method to Combine Underline Styles

We can combine multiple underline styles together into a compound style. At the bit-wise level, this is accomplished by taking the logical OR of the integers representing two styles. Being an OptionSet, NSUnderlineStyle provides a Swifty alternative. The union(_:) method on NSUnderlineStyle effectuates the logical OR in a more plain-English fashion. As an example:

NSUnderlineStyle.double.union(.patternDot).rawValue

This code produces an Int with the appropriate bits flipped, and TextKit draws a very pretty dotted double-underline. Of course, not all combinations work. 'NSAttributedString' might accept anything, but common sense and the TextKit engine ultimately will dictate.



Related Topics



Leave a reply



Submit