emoji not being displayed, weird characters instead - ios

I'm trying to display an emoji (ascii #55357) in CoreText and this is what I'm getting:
It displays two of these characters and inserts the cursor in the middle. I'm not going to include my CoreText code because it's such a mess and I have no idea where the bug is originating from, but what I was just curious has anyone else seen the same problem before in any facet of iOS and what is the meaning of these sort of A in a black and white box characters that got displayed? Does it mean invalid character or something? Just looking for some hints on how to even approach this problem.

The problem was that I didn't realize an emoji character has a length of 2 and not 1 like most other characters. So what specifically was causing the issue was I was applying attributes to the emoji when adding it to my NSMutableAttributedString over a length 1 instead of 2. When I changed it to 2 it fixed it:
[self.text addAttributes: attributes range:NSMakeRange(self.cursor.position, 2 /* not 1 */)]

Related

CTRunGetAdvances doesn't return zero for Arabic diacritics

I'm trying to draw Arabic glyphs manually on iOS, and I've stumbled upon a specific problem regarding Arabic diacritics. When trying to get the advance of the glyph with CTRunGetAdvances, I expect to get a width of value 0, but I get a value like with any other character. Is there something I'm missing?
When I say Arabic diacritics, I mean characters on this list with hexadecimal values ranging from FE70 to FE7F (inclusive). One example is ﹰ Arabic Fathatan Isolated Form.
I should mention that I do not know Arabic well and may be overseeing something that is obvious to a native Arab. Any suggestions are welcome.

How can I standardize the the varying truncating dot characters of UILabel?

I have a plist file which I decode to load data onto my application.
This plist file contains String type values that gets mapped to UILabel's text property.
I noticed that the truncating behavior of the text in the label is not always the same.
To be more specific, the three dots that are added when the text is truncated are, as opposed to my expectation, two kinds: one being ... and the other being ⋯ which appears to be this unicode character in this link.
I checked UILabel's attribute settings but I was unable to find any settings related to this behavior.
Has anyone else experienced this problem and standardized the truncating character to be ...?
Here is the image describing the problem mentioned above. Both labels have 2 lines and have new line escape character inserted between the first line and the second line of text. I am posting a link to this image because apparently I don't have enough reputation to post an image.
varying truncating characters of UILabel
IMO this is a bug in UILabel, and it may be worth opening a Feedback about it.
TL;DR: I recommend using TTTAttributedLabel.
Long-winded answer, because this was such an interesting question:
UILabel uses a different ellipsis based on the language script being truncated. As you've noticed, for most scripts, they use HORIZONTAL ELLIPSIS (…), or something very similar. But for Chinese, Japanese, and Korean (CJK), they use MIDLINE HORIZONTAL ELLIPSIS (⋯), or again, something very similar. The only other exception I've found is Burmese, which uses three circles that I don't recognize.
In my tests, all the following used …: Latin, Cyrillic, Bengali, Arabic, Hebrew, Hindi, Thai, Kannada, Nepali, and Mongolian (I kid. iOS can't layout Mongolian. Nobody can layout Mongolian, but it still uses …). UILabel even uses … for Lao, even though I thought ຯ was specifically for that, but I guess eventually everything becomes Latin.
The problem with UILabel being so clever for CJK and Burmese is that it decides what character to use exclusively by looking at the first character being removed. And it thinks SPACE is Latin (or at least not "special").
So what to do? My recommendation is probably to use TTTAttributedLabel, since it lets you configure the truncation character, and more importantly, is open source so you can fix it if it's not working the way you want.
The second option would be to truncate the text by hand using techniques like the one described in How to change truncate characters in UILabel?. There are probably better ways to do it using CTFrameGetVisibleStringRange instead of constantly shrinking the string until it fits, but I don't know if it's worth the effort. (If that path sounds useful, I could probably write up something that does it. It's just probably not worth the trouble.)
And the final option I know is to replace the SPACE character with an "equivalent" CJK character. The closest I've found that works is HANGUL FILLER (U+3164), but I don't like it. It's too wide, and I expect that it will make Korean uncomfortable to read (but I rarely try to read Korean, so I may be wrong here):
With SPACE: 안녕 하세요
With FILLER: 안녕ㅤ하세요
There's also HALFWIDTH HANGUL FILLER (U+FFA0), which is better, but UILabel seems to make it zero width (this may be a font issue, so maybe worth trying):
With SPACE: 안녕 하세요
With HALF: 안녕ᅠ하세요
let string = "안녕 하세요"
let filler = "\u{3164}"
label.text = string.replacingOccurrences(of: " ", with: filler)
OTOH, you may run into the same problem if you use any other non-CJK characters, like Latin punctuation or Arabic numerals. So this solution may not scale. And you should make sure that Voice Over properly ignores it.

Slight FROWNING face unicode in iOS

I want to display slightly FROWNING face in my UILabel and the unicode whihc i am using is \u2639 but that's displaying white frowny face but i needed the yellow one. I checked everywhere but its the same unicode everywhere. could somebody tell me what is the unicode for yellow frowning face?
Edit - Attached is the screenshot for which i am looking for unicode which should be the one which i posted above but that is giving me white frowning face not the yellow one.
The slightly frowny face is U+1F641.
However, let's return to your original question. You are setting the label's text to "\u{2639}" and you are seeing the white frowny face.
The solution is to specify the variant of this glyph, like this: "\u{2639}\u{FE0F}". If you set the label's text to that, you will see the yellow frowny face.
(To understand why that is and what the variation selector means, see https://unicode.org/reports/tr51/#Emoji_Variation_Sequences. Basically, this unicode codepoint falls in the older text area, so if you want the newer emoji variant, you have to ask for it.)
But an even simpler solution is: don't use codepoint values at all! Swift strings are unicode. Just include the emoji directly in your string. Set the label's text to "☹️"! For example:
self.label.text = "☹️"
That way, you will see the emoji you specified in the string.

How to stop UILabel from replacing "..." with an ellipsis character

I have an iOS app which uses fixed width font label extensively.
After changing to the iOS 7 sdk and build target 6.1, all the label automagically replace occurences of three punctuation marks with an ellipsis character. This breaks a lot of stuff and looks weird, since the ellipsis character is not present in the font I use, and iOS sees fit to use one from a different font.
How do I stop this behaviour?
This is a ligature, and iOS seems to replace them automatically (like fl becomes fl). Seems like there are some options to disable them, see this question: Adjoining "f" and "l" characters
Alternative number three: insert a zero-width space (U+200B) between the dots.
(Posted as an answer per request of the OP)
One way around this is to replace the ASCII periods with a unicode 2024 character ("ONE DOT LEADER"). It looks exactly like a period but should not get converted automatically.
What you could do if this is widespread is to change all your UILabels to a subclass, MyLabel, and intercept messages to set the text, look for three dots, and if found change them to the unicode character above.
Yeah, this is a big PITA but I know of no other workaround.
EDIT
Another idea - find an open source UILabel (there must be at least one) and use it.
Another alternative : the ellipsis is a true character of its own. Why don't you try to add it yourself in your font (with Fontlab, FontForge or Glyphs) at the same width than the other characters?

How do I automatically truncate a UILabel on word boundaries with ellipsis?

I have a 1-line label that I want to truncate on word boundaries and add ellipsis (i.e. "The quick brown fox..." instead of "The quick brown fix jum...". Is there an easy way to achieve this? I've tried setting lineBreakMode to UILineBreakModeTailTruncation, UILineBreakModeWordWrap, and UILineBreakModeTailTruncation | UILineBreakModeWordWrap and none of these get the desired behavior. I've also tried their NSLineBreak... counterparts.
I got this working by customizing this example.
My code uses -[NSString enumerateSubstringsInRange:options:usingBlock:] to find words, and then for each word found I check -[NSString boundingRectWithSize:options:attributes:context:] to find if the string still fits my width limit. If the string up to latest found word goes over my limit, I'd use the last word found as the final word of my truncated string.
Just append ellipsis at the end of string and profit!

Resources