How to display the emoji and special characters in UIlabel and UItextviews?
Emoji characters are in unicode plane 1 and thus require more than 16 bits to represent a code point. Thus two UTF8 representations or one UTF32 representation. Unicode is actually a 21-bit system and for plane 0 characters (basically everything except emoji) 16 bits is sufficient and we get by using 16 bits. Emoji need more than 16 bits.
"Youtube\ud83d\ude27\ud83d\ude2e\ud83d\ude2f\ud83d"
. is invalid, it is part of a utf16 unicode escaped string, the last \ud83d
is 1/2 of an emoji character.
Also, inorder to create a literal string with the escape character "\" the escape character must be escaped: "\\".
NSString *emojiEscaped = @"Youtube\\ud83d\\ude27\\ud83d\\ude2e\\ud83d\\ude2f";
NSData *emojiData = [emojiEscaped dataUsingEncoding:NSUTF8StringEncoding];
NSString *emojiString = [[NSString alloc] initWithData:emojiData encoding:NSNonLossyASCIIStringEncoding];
NSLog(@"emojiString: %@", emojiString);
NSLog output:
emojiString: Youtube/p>
The emoji string can also be expressed in utf32:
NSString *string = @"\U0001f627\U0001f62e\U0001f62f";
NSLog(@"string: %@", string);
NSLog output:
string1: /p>
Set text(with emojis, special chars, links) in UILabel, and link should be clickable
I needed this kind of linked text for another project last month. I created a custom UITableViewCell with a UITextView object in the cell, subclassed to a custom UITextView subclass. I just made a quick demo project and put it up on git for you now. Feel free to use it.
github.com/fareast555/MPC_LinkedTextView
The basic secret sauce for using text links is the NSLinkAttributeName attribute in the mutable text, and telling the system to handle links.
- (void)updateTextViewWithFullText:(NSString *)fullText linkTriggerText:(NSString *)triggerText linkURLString:(NSString *)urlString
{
//Create a mutable string based on the full text
NSMutableAttributedString *mutableString = [[NSMutableAttributedString alloc]initWithString:fullText attributes:nil];
//Add the link attribute across the range of the target text
[mutableString addAttribute:NSLinkAttributeName value:urlString range:[fullText rangeOfString:triggerText]];
//Add any other font or color bling as needed
[mutableString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:18 weight:UIFontWeightMedium] range:NSMakeRange(0, [fullText length])];
//Set the mutable text to the textfield
[self setAttributedText: mutableString];
}
#pragma mark - UITextViewDelegate
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction
{
return YES;
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
return NO;
}
And for textviews, you'll find it easier to use auto layout if you turn off scrolling.
#pragma mark - Configure
- (void)_configureTextView
{
self.delegate = self;
[self setEditable:NO];
[self setSelectable:YES];
[self setScrollEnabled:NO];
[self setUserInteractionEnabled:YES];
[self setDataDetectorTypes:UIDataDetectorTypeLink];
self.scrollIndicatorInsets = UIEdgeInsetsZero;
}
Detect if a user has typed an emoji character in UITextView
Over the years these emoji-detecting solutions keep breaking as Apple adds new emojis w/ new methods (like skin-toned emojis built by pre-cursing a character with an additional character), etc.
I finally broke down and just wrote the following method which works for all current emojis and should work for all future emojis.
The solution creates a UILabel with the character and a black background. CG then takes a snapshot of the label and I scan all pixels in the snapshot for any non solid-black pixels. The reason I add the black background is to avoid issues of false-coloring due to Subpixel Rendering
The solution runs VERY fast on my device, I can check hundreds of characters a second, but it should be noted that this is a CoreGraphics solution and should not be used heavily like you could with a regular text method. Graphics processing is data heavy so checking thousands of characters at once could result in noticeable lag.
-(BOOL)isEmoji:(NSString *)character {
UILabel *characterRender = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
characterRender.text = character;
characterRender.backgroundColor = [UIColor blackColor];//needed to remove subpixel rendering colors
[characterRender sizeToFit];
CGRect rect = [characterRender bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
CGContextRef contextSnap = UIGraphicsGetCurrentContext();
[characterRender.layer renderInContext:contextSnap];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef imageRef = [capturedImage CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;
CGContextRef context = CGBitmapContextCreate(rawData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
BOOL colorPixelFound = NO;
int x = 0;
int y = 0;
while (y < height && !colorPixelFound) {
while (x < width && !colorPixelFound) {
NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
CGFloat red = (CGFloat)rawData[byteIndex];
CGFloat green = (CGFloat)rawData[byteIndex+1];
CGFloat blue = (CGFloat)rawData[byteIndex+2];
CGFloat h, s, b, a;
UIColor *c = [UIColor colorWithRed:red green:green blue:blue alpha:1.0f];
[c getHue:&h saturation:&s brightness:&b alpha:&a];
b /= 255.0f;
if (b > 0) {
colorPixelFound = YES;
}
x++;
}
x=0;
y++;
}
return colorPixelFound;
}
Getting a normal looking unicode down arrow in a UILabel like this ⬇
Displaying some characters as "Emojis" is a feature which is e.g. (controversially) discussed here: https://devforums.apple.com/message/487463#487463 (requires Apple Developer login). This feature was introduced in iOS 6.
A solution (from https://stackoverflow.com/a/13836045/1187415) is to append the Unicode "Variation selector" U+FE0E, e.g.
self.myLabel.text = @"\u2B07\uFE0E";
// or:
self.myLabel.text = @"⬇\uFE0E";
Note that on iOS <= 5.x, the Variation selector is not necessary and must not be used, because iOS 5 would display it as a box.
In Swift it would be
myLabel.text = "⬇\u{FE0E}"
Related Topics
How Detect Swipe Gesture Direction
How to Create Different User Groups in Firebase
Open Installed Pwa from External Url
How to Convert Fbprofilepictureview to an Uiimage
Searching Nsarray of Nsdictionary Objects
Swift: Random Number for 64-Bit Integers
Fcm Push Notifications Do Not Work on iOS 11
-[Not a Type Retain]: Message Sent to Deallocated Instance
Swift - Checking Unmanaged Address Book Single Value Property for Nil
Delete App from Itunes Connect
Add Cocoapods to Tests Target Too
Create Singleton of a Viewcontroller in Swift 3
Nsoperationqueue Serial Fifo Queue
How to Set Http Header Fields in Objective-C
How to Get a Swift Type Name as a String with Its Namespace (Or Framework Name)