Gene S
Gene S

Reputation: 553

NSAttributedString and emoji: the range I never set seems to be set

This is the most weird problem (XCode 10.2.1 playground):

let a = "String with emoji πŸ”‘"
var b = "00:00 0000"

var nsa = NSMutableAttributedString(string: a)
var nsb = NSMutableAttributedString(string: b)
nsb.addAttributes([.foregroundColor: UIColor.red], 
                  range: NSRange(location: 0, length: nsb.length))
nsa.append(nsb)

and the nsa looks like this:

enter image description here

The 00 after the emoji has the same width and height as the emoji character. But it gets weirder. The effect is extended only over digits 0-9, space, and hash (#) characters. If I replace the 00:00 0000 with a different string then everything is perfectly normal:

enter image description here

It seems like internally NSMutableAttributedString applies an attribute to the emoji character and then incorrectly extends it to the attached string's prefix composed of certain characters.

Is this a known problem? I found a workaround by appending a thin non-breaking space character to the first string a + "\u{2009}". Is there a better way of dealing with emoji weirdness in Swift?

Upvotes: 4

Views: 860

Answers (2)

Gene S
Gene S

Reputation: 553

Here is Apple's official answer:

We have determined that this is an issue for you to resolve.

Since the app is not explicitly specifying the font to the attributed string, it’s relying on the font fallback system.

It is recommended to specify the font attribute all the time since the contextual nature of the text system might produce unexpected result like this.

Please let us know whether the issue is resolved for you by updating your bug report.

This is just appalling.

Upvotes: -1

rmaddy
rmaddy

Reputation: 318954

The display issue happens in the playground display of the attributed string. It also happens if you use the attributed string in a UITextView. But the problem does not happen in a UILabel.

All of the display issues go away if you give the attributed string a font.

Adding:

nsa.addAttributes([.font: UIFont.systemFont(ofSize: 16)],
    range: NSRange(location: 0, length: nsa.string.utf16.count))

after appending the two strings makes the all of the issues go away. Obviously you should use whatever desired font you want.

You should always apply a font to an attributed string so the UI components know how to properly display the content of the attribute string.

Upvotes: 2

Related Questions