0

enter image description hereIve been trying to find a solution to my problem all day with no success. I know its probably something silly since I am still new to OBjective C so heres my issue.

I'm trying to implement unicode Emoji Characters into a UILabel. So lets take it one step at a time.

Here is the Json String I am using:

"body":"\\U0001f61f \\U0001f62e \\U0001f621"

As you can see the Json Serializer im using escapes the unicode. I suspect this is my main problem.

I am retrieving the data like so:

  dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{

    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    NSString *concat=[NSString stringWithFormat:@"MYURL?ID=%@",_TID];
    NSURL *url = [NSURL URLWithString:concat];
    NSData *jsonData=[NSData dataWithContentsOfURL:url];

    dispatch_async(dispatch_get_main_queue(), ^{
        if (jsonData!=nil) {
            newX= [[NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil]mutableCopy];
            pageCounter=2;
            [self.topicView reloadData];
            [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;            }
        [loadingView
         performSelector:@selector(removeView)
         withObject:nil
         afterDelay:1];
    });
});

After some time later the data is called and added to the UILabel.

UILabel *emo=(UILabel*)[Tcell viewWithTag:6];
   NSString*body=[[[newX objectAtIndex:indexPath.row] valueForKey:@"body"] mutableCopy];
   emo.text=body;

Which just gives me \U0001f61f \U0001f62e \U0001f621 as text. I know its probably just an encoding issue but I have no idea where to attack this.

Any help would be appreciated. :)

Anthem127
  • 169
  • 2
  • 10
  • What font is the label set to ? – Wain Jun 20 '13 at 19:29
  • You need to determine who is first encoding the Emoji characters as “\U0001f61f”, and then who is double escaping the slashes. It has to be some part of your server. If you want to send just the first emoji, for example, and you are using UTF-8 as output encoding (pretty likely), the body should look like “\uf09f\u989f” (notice the small case u, and that there is two UTF-8 chars in there for one emoji). – yonosoytu Jun 20 '13 at 19:37
  • I am storing these Characters in SQL by hand because they need to be paired with other Emoticons. ASP.net handles the JSON request which I believe i'm encoding correctly. – Anthem127 Jun 20 '13 at 20:12
  • yonosoytu is correct. According to the [JSON RFC](http://www.ietf.org/rfc/rfc4627.txt), characters that are not part of the "Basic Multilingual Plane" can be escaped using a UTF-16 surrogate pair. For `U+U0001f61f` that would be `\uD83D\uDE1F`. And this would then be correctly decoded by NSJSONSerialization. So it seems to me that your server is encoding the emoji incorrectly. – Martin R Jun 20 '13 at 20:27
  • @Anthem127: According to your image, some Emojis are displayed correctly, some as `<0001f60a>` and some as `\U0001f61f`. Is that correct? Can you show the NSLog output of `jsonData`? – Martin R Jun 20 '13 at 20:45
  • The emoji that is showing is hard coded into the string and here is a link to a screen capture of the log. http://www.liweddings.com/i/fm/1.png – Anthem127 Jun 20 '13 at 21:02
  • The string for the body object looks like this when its done though `<0001f60a> \U0001f61f \U0001f62e \U0001f621 \u1F601 %20U0001F609 \u1F628 😞 U+1F60C \uD83D\uDE1F` – Anthem127 Jun 20 '13 at 21:07
  • I don't know much about ASP.net but I am fairly sure that `"\\U0001f61f"` is not the correct way to put a Unicode character into JSON. – Martin R Jun 20 '13 at 21:10
  • Ok, so I went and stored these unicode characters into a `.plist` and replaced the string that needed to be replaced with the object in the `.plist` and I still get the same thing. Starting to think its something with the label. – Anthem127 Jun 20 '13 at 22:59

4 Answers4

1

When your json string is "\U0001f61f" json understands \\ as an escape to represent a literal slash. You should only use a single slash if you want the "U" and hexadecimal digits themselves to be escaped.


When you create a string like this:

NSString *s = @"\U0001f61f \U0001f62e \U0001f621";

You get emoji characters because the Objective-C compiler understands and transforms the \U escapes (called Universal Character Names, from C and C++) to the appropriate characters in string literals. If you use a string from json, or a plist, or anything other than a string literal the escape sequence will not be processed at compile time by the Objective-C compiler.


Note: See the C or C++ language specifications to see how escapes in string literals are processed in Objective-C or Objective-C++.


Instead you want to create a string in json using escapes json understands. Unfortunately json is deficient in its Unicode support for characters outside the BMP (i.e., greater than U+FFFF). json has a \u escape, but it only supports four hexadecimal digits. To use this with characters outside the BMP there's a hack that involves using surrogate codepoints just as UTF-16 does.

The json string that encodes the characters you want is:

"body":"\uD83D\uDE1F \uD83D\uDE2E \uD83D\uDE21"

(If you use Google to search for a Unicode character using the format U+123456 it will find a page that tells you the UTF-16 encoding.)

Hopefully this is the only change you need to make, however I'm unsure if NSJSONSerialization supports this hack. If this doesn't work on its own you'll need to take a look at the documentation (assuming the behavior is documented) for how NSJSONSerialization produces string data from json data.

bames53
  • 86,085
  • 15
  • 179
  • 244
1

I use the below code to encode emoji character

NSString *uniText = [NSString stringWithUTF8String:[textview.text UTF8String]]; NSData *msgData = [uniText dataUsingEncoding:NSNonLossyASCIIStringEncoding]; NSString *goodMsg = [[NSString alloc] initWithData:msgData encoding:NSUTF8StringEncoding] ;

And the below code to decode and display in UILabel

const char *jsonString = [body UTF8String]; NSData *jsonData = [NSData dataWithBytes:jsonString length:strlen(jsonString)]; NSString *goodMsg = [[NSString alloc] initWithData:jsonData encoding:NSNonLossyASCIIStringEncoding];

Karun
  • 880
  • 1
  • 8
  • 19
0

To display those characters you need to use a font in which they are valid. On iOS that means using the Apple Color Emoji font.

Wain
  • 118,658
  • 15
  • 128
  • 151
  • All that did was change the font style. :/ – Anthem127 Jun 20 '13 at 19:40
  • Are you stripping the leading (extra) `\` ? – Wain Jun 20 '13 at 19:43
  • Ive tried using a replace function and tried using http://stackoverflow.com/a/7935625/870806 niether worked. Im not sure if I have to enable some UNicode filter for the Json reader but im unfamiliar with OC. – Anthem127 Jun 20 '13 at 19:47
  • So you used `stringByReplacingOccurrencesOfString` to replace \\ with \ ? – Wain Jun 20 '13 at 19:49
  • body=[body stringByReplacingOccurrencesOfString: @"\\\\" withString:@"\\"]; I have several other emoji characters working as string literals, but as soon as I try to use anything from the json string from the server nothing works. – Anthem127 Jun 20 '13 at 19:54
  • You don't have to assign a special font to UILabel to display Emojis. I tried this several times and it works without problem. (Maybe the font is switched internally if necessary.) – Martin R Jun 20 '13 at 20:31
  • @MartinR Do you know which version of iOS (or all)? And does it give the full colour version? I'm sure I remember having to set the correct font previously. – Wain Jun 20 '13 at 20:35
  • `self.label.text = @"\U0001f61f \U0001f62e \U0001f621";` just works in the iOS 6 Simulator and displays " " (with colors). In the iOS 5 Simulator, only the last Emoji is displayed correctly, so the set of supported Emojis is different. - I might be wrong but I assume that this is more a problem how Unicodes are encoded in JSON, and less a font problem. – Martin R Jun 20 '13 at 20:42
  • Im working with IOS 6.1. Its got ZERO to do with the Json. Like I stated before I stored these characters in a .plist and it still didnt work. The only way im having any luck is if I write them out manually in a NSMutableDictionary. Xcode sees it as a "Universal Character" then and only then. – Anthem127 Jun 21 '13 at 09:50
0

So after spending all day doing this the ONLY solution I found was to create an NSMutableDictionary and call the keys from there.

Anthem127
  • 169
  • 2
  • 10