2

I have Unicode Hex Character Code &#x1f682 that I receive from a server request, and I want to convert it to the Steam Locomotive emoji in my UILabel. I have read many other posts on the issue, but none of the solutions seem to work.

I have read posts about decoding HTML entities or setting the NSString as a UFT8 string, but none of those work.

NSString *unicode = @"Train &#x1f682";
self.label.text = [unicode stringByDecodingHTMLEntities]; <---- Doesn't work

Tried this:

NSString *train = @"Train &#x1f682";
self.label.text = [NSString stringWithUTF8String:[train UTF8String]]; <---- Doesn't work

Any ideas on how to convert this so I can see the emoji in my UILabel?

Note: This is different from the other questions about unicode characters, as this format has not been addressed and a solution proposed.

Nic Hubbard
  • 41,587
  • 63
  • 251
  • 412
  • Different format there, but same idea: scan the string to figure out the bytes. – jscs Jul 13 '16 at 23:08
  • Josh, can you explain how I would do that? – Nic Hubbard Jul 13 '16 at 23:11
  • Is the procedure there not clear? – jscs Jul 13 '16 at 23:19
  • Wrote this up while it was apparently being marked duplicate: NSString *train = @"\xF0\x9F\x9A\x82"; NSData *data = [train dataUsingEncoding:NSNonLossyASCIIStringEncoding]; NSString *newEncoding = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSData *newdata=[newEncoding dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]; NSString *finalString=[[NSString alloc] initWithData:newdata encoding:NSNonLossyASCIIStringEncoding]; self.label.text = finalString; – bradkratky Jul 13 '16 at 23:19
  • The string does not contain those bytes, @bradkratky, it contains the _characters_ '&', '#', 'x', '1', 'f', '6', '8', '2'. – jscs Jul 13 '16 at 23:22
  • Exactly, so using the SO post above, I don't see how to convert my hex unicode... – Nic Hubbard Jul 13 '16 at 23:23
  • @JoshCaswell It does, that's why the encoding is changed. When I run on simulator I get the steam engine he's looking for. http://apps.timwhitlock.info/unicode/inspect/hex/1F682 – bradkratky Jul 13 '16 at 23:23
  • Oh my mistake. Thought you just wanted the train. Sorry about that. – bradkratky Jul 13 '16 at 23:23
  • 1
    @JoshCaswell - Nevermind, I got it working...will post an answer. – Nic Hubbard Jul 13 '16 at 23:24

1 Answers1

0

I got it working using the following:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.label.text = [self convertHexUnicodeString:@"This is a train &#x1f682 I like trains! &#x1f682"];

}

- (NSString *)convertHexUnicodeString:(NSString *)unicodeText {

    NSScanner *myScanner;
    NSString *text = nil;
    myScanner = [NSScanner scannerWithString:unicodeText];

    while ([myScanner isAtEnd] == NO) {

        [myScanner scanUpToString:@"&#x" intoString:NULL] ;
        [myScanner scanUpToString:@" " intoString:&text] ;
        unicodeText = [unicodeText stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@", text] withString:[self replaceHexUnicode:text]];
    }

    unicodeText = [unicodeText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    return unicodeText;
}

- (NSString *)replaceHexUnicode:(NSString *)text {

    text = [text substringFromIndex:3];

    unsigned unicodeInt = 0;
    [[NSScanner scannerWithString:text] scanHexInt:&unicodeInt];
    char chars[4];
    int len = 4;
    chars[0] = (unicodeInt >> 24) & (1 << 24) - 1;
    chars[1] = (unicodeInt >> 16) & (1 << 16) - 1;
    chars[2] = (unicodeInt >> 8) & (1 << 8) - 1;
    chars[3] = unicodeInt & (1 << 8) - 1;

    return [[NSString alloc] initWithBytes:chars length:len encoding:NSUTF32StringEncoding];

}
Nic Hubbard
  • 41,587
  • 63
  • 251
  • 412