Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emoji loss when using NSMutableAttributedString on UILabel

I have got some strange problem while using NSMutableAttributedString for setting text part on UILabel. It shows some bizarre symbol for specific emojis. Here's the code i use and the screenshot of the problem.

guard var _comment = comment.comment ,let _username = comment.userName else { return }
var username = NSMutableAttributedString.init(string: _username)
var commentText = NSMutableAttributedString.init(string: _comment)
var commentTotal = NSMutableAttributedString.init()
commentTotal.append(username)
commentTotal.append(commentText)
self.userNameLabel.attributedText = commentTotal

Screenshot :

enter image description here

But if i directly put the string without using NSMutableAttributedString like this:

self.userName.text = _comment

The output of this shows the correct emoji without problem .What would be the problem here? Anyone with a suggestion? enter image description here

This is the code for setting fonts :

if let font = UIFont.init(name: "Montserrat-Bold", size: self.userNameLabel.font.pointSize){
        username.addAttribute(NSFontAttributeName, value: font, range: NSRange.init(location: 0, length: _username.count))
        username.addAttribute(NSForegroundColorAttributeName, value: UIColor.init(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0), range: NSRange.init(location: 0, length: _username.count))
    }



if let font = UIFont.init(name: "Montserrat-Medium", size: self.userNameLabel.font.pointSize-1){
                    commentText.addAttribute(NSFontAttributeName, value: font, range: NSRange.init(location: 0, length: commentString.count))
                    commentText.addAttribute(NSForegroundColorAttributeName, value: UIColor.init(red: 0/255, green: 0/255, blue: 0/255, alpha: 1.0), range: NSRange.init(location: 0, length: commentString.count))
                }

Storyboard Image: enter image description here

like image 891
umutg4d Avatar asked Jun 20 '18 18:06

umutg4d


2 Answers

Your problem is with your NSRange calculations when setting the attributes. NS[Mutable]AttributeString needs the NSRange to be based on NSString ranges, not String ranges.

So code like:

NSRange.init(location: 0, length: commentString.count)

Needs to be written as either:

NSRange(location: 0, length: (commentString as NSString).length)

or:

NSRange(location: 0, length: commentString.utf16.count)

The following demonstrates the issue with commentString.count:

let comment = "💃👍👍"
print(comment.count) // 3
print((comment as NSString).length) // 6
print(comment.utf16.count) // 6

This is why your code seems to be splitting the middle character in half. You are passing in half (in this case) the needed length.

like image 139
rmaddy Avatar answered Sep 20 '22 23:09

rmaddy


Proper way to do this in Swift 4 is using indexes on String:

NSRange(location: 0, length: commentString.endIndex.encodedOffset)
like image 29
Milan Nosáľ Avatar answered Sep 22 '22 23:09

Milan Nosáľ