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
Swift: Google Maps Draw Waypoint Polyline
Swift. Combine. How to Call a Publisher Block More Than Once When Retry
How to Rotate an Object Around Only One Axis in Realitykit
How to Combine Two Nsdictionary in Swift
Why Do Two Distinct Array Literals Equal Each Other in Swift
Swift Realm: After Writing Transaction Reference Set to Nil
Differences Generic Protocol Type Parameter VS Direct Protocol Type
Implementing Stringliteralconvertible on Nsurl
Swift 1.2 Not Working with Same Function Name and Different Parameter
How to Get Rid of Array Brackets While Printing
Display Table View When Searchbar (From Searchcontroller) Begin Edited Swift
Set a Variable to the < ("Less Than") Operator as a Function in Swift
Extending Typed Array by Conforming to a Protocol in Swift 2
Count the Number of Lines in a Swift String
Can Not Cast Value of Type Nstaggedpointerstring to Nsdictionary
Loading Views into Nscontainerview with Swift