Display Unicode String as Emoji - ios

I currently receive emojis in a payload in the following format:
\\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F
which represents "🚣‍♀️"
However, if I try to display this, it only shows the string above (escaped with 1 less ), not the emoji e.g.
NSString *emoji = payload[#"emoji"];
NSLog(#"%#", emoji) then displays as \U0001F6A3\U0000200D\U00002640\U0000FE0F
It's as if the unicode escape it not being recognised. How can I get the string above to show as an emoji?
Please assume that the format the data is received in from the server cannot be changed.
UPDATE
I found another way to do it, but I think the answer by Albert posted below is better. I am only posting this for completeness and reference:
NSArray *emojiArray = [unicodeString componentsSeparatedByString:#"\\U"];
NSString *transformedString = #"";
for (NSInteger i = 0; i < [emojiArray count]; i++) {
NSString *code = emojiArray[i];
if ([code length] == 0) continue;
NSScanner *hexScan = [NSScanner scannerWithString:code];
unsigned int hexNum;
[hexScan scanHexInt:&hexNum];
UTF32Char inputChar = hexNum;
NSString *res = [[NSString alloc] initWithBytes:&inputChar length:4 encoding:NSUTF32LittleEndianStringEncoding];
transformedString = [transformedString stringByAppendingString:res];
}

Remove the excess backslash then convert with a reverse string transform stringByApplyingTransform. The transform must use key "Any-Hex" for emojis.
NSString *payloadString = #"\\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F";
NSString *unescapedPayloadString = [payloadString stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"];
NSString *transformedString = [unescapedPayloadString stringByApplyingTransform:#"Any-Hex" reverse:YES];
NSLog(#"%#", transformedString);//logs "🚣‍♀️"

I investigated this, and it seems you may not be receiving what you say you are receiving. If you see \U0001F6A3\U0000200D\U00002640\U0000FE0F in your NSLog, chances are you are actually receiving \\U0001F6A3\\U0000200D\\U00002640\\U0000FE0F at your end instead. I tried using a variable
NSString *toDecode = #"\U0001F6A3\U0000200D\U00002640\U0000FE0F";
self.tv.text = toDecode;
And in textview it is displaying the emoji fine.
So you got to fix that first and then it will display well.

Related

how to capture a single character from NSString using substringToIndex

I have a NSString that has two characters.
The NSSring looks something like this
FW
I use this code to capture the first character
NSString *firstStateString = [totInstStateString substringToIndex:1];
this pecie of code returns F, I would like to know how to return the second character to its own string using substringToIndex.
anyhelp would be appreciated.
Use substringWithRange:
For Example :
[#"fw" substringWithRange:NSMakeRange(1, 1)];
will get you #"w"
have a look at the apple docs
Use following code .. My be helpful in your case.
NSString *myString = #"FFNNF";
for(int i = 0; i < [myString length]; i++)
{
NSLog(#"%#", [myString substringWithRange:NSMakeRange(i, 1)])
}
Also check This Question.
How to get a single NSString character from an NSString
The other option is:
NSString *lastStateString = [totInstStateString substringFromIndex:1];
This will get the last character of a two-character string. You might want to do some bounds checking somewhere in there.

NSArray element to NSString

I have application where I receive from socket message like: "\r\nIDLE|03/17/2013 19:48\n". I convert this message into UTF8 string with code:
NSString* newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
then I try to separate command and time from this string:
NSArray *nums = [command componentsSeparatedByString:[NSString stringWithFormat:#"%c", (char)13]];
NSLog(#"First separate = %#", nums);
if ([nums count] == 3)
{
NSArray *nums1 = [[nums objectAtIndex:1] componentsSeparatedByString:#"|"];
NSLog(#"second separate = %#", nums1);
if ([nums1 count] == 2)
{
NSString* strState = [(NSString *)[nums1 objectAtIndex:0] description];
NSLog(#"State = %#", strState);
...
}
}
in the log I see next:
First separate = (
"IDLE|03/17/2013 19:48",
"\n"
second separate = (
"IDLE",
"03/17/2013 19:48"
State = I
After second separating in the 0 elements I have text IDLE, but when I try to get this text I strState variable, I see only first character of this text.
Can anybody help me get full command of this element?
Thank you.
UPDATE1
As I say previously I get from socket message like:"\r\nIDLE|03/17/2013 19:48\n"
I'm sure that the server send me this message.
in the Socket read callback I'm use next code for reading this message:
int result = CFReadStreamRead(_inputStream, (UInt8*)[data mutableBytes], length);
NSString* newStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
Here app read 50 bytes and this is right for this message? you can see my debugger at this point in the next picture:
but in the newStr member I see only \r.
then I send try separate this message with code I wrote above.
When I try separate message logger show me all message instead of \r:
Thank you
Have you considered using sscanf()?
char command[COMMAND_SIZE_LIMIT];
char date[DATE_SIZE_LIMIT];
char time[TIME_SIZE_LIMIT];
sscanf (input, "\r\n%[^|]%*[|]%s%s\n", command, date, time);
(Note: Above is example code; you've got a security issue if the scanned string has oversized command or datetime substrings.)
# test
ebg#ebg$ ./foo
Input: '
IDLE|03/17/2013 19:48
'
Command: 'IDLE'
Date: '03/17/2013'
Time: '19:48'
It is easy to convert NSString <==> C string.
There is a fairly straightforward way to accomplish what you want using the -[NSString stringByTrimmingCharactersInSet:] method. Passing the whitespace and newline character set allows you to trim the leading and trailing whitespace and newlines from your string, and then you only need to do a single call to componentsSeparatedByString:.
NSString *raw = #"\r\nIDLE|03/17/2013 19:48\n";
NSString *trimmedString = [raw stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSArray *components = [trimmedString componentsSeparatedByString:#"|"];
NSString *command = components[0];
NSString *time = components[1];
NSLog(#"command = %#, time = %#",command,time);
This code yields the following output:
command = IDLE, time = 03/17/2013 19:48

Extracting from the right of a string in objective C [duplicate]

This question already has answers here:
Get last 2 characters of a string?
(2 answers)
Closed 9 years ago.
This seems to be what I'm looking for but in reverse. I would like the string to extract from the right not from the left.
The example extracting from the left is given:
NSString *source = #"0123456789";
NSString *firstFour = [source substringToIndex:4];
Output: "0123"
I'm looking for a version of the below that works from the right (what is below doesn't work)
NSString *source = #"0123456789";
NSString *lastFour = [source substringToIndex:-4];
Output: "6789"
the [source substringFromIndex:6]; won't work because sometimes I will get an answer that is 000123456789 or 456789 or 6789. In all cases I just need the last 4 characters from the string so that I can convert it to a number.
there must be a better way than a bunch of if else statements?
As you are not sure, about the length of the string, so you must check it before extracting like this:
NSString *source = #"0123456789";
NSNumber *number;
if (source.length>=4) {
NSString *lastFour=[source substringFromIndex:source.length-4];
number=#([lastFour integerValue]); //and save it in a number, it can be int or NSInteger as per your need
}
NSLog(#"%#",number);
Also if you want a quick method that you need to call several times, create a category :
#implementation NSString (SubstringFromRight)
-(NSString *)substringFromRight:(NSUInteger)from{
if (self.length<from) {
return nil;
}
return [self substringFromIndex:self.length-from];
}
#end
And use it as :NSLog(#"%#",[source1 substringFromRight:4]);
NSString *source = #"0123456789";
NSString *newString = [source substringFromIndex:[source length] - 4];
NSLog(#"%#",newString);
replace
NSString *lastFour = [source substringToIndex:-4];
with
NSString *lastFour = [source substringFromIndex:[source length] - 4];
which returns you the last 4 characters of your original string string in lastFour string.
You can use the following code to get last 4 characters from your string.
NSString *last4Characters = [source substringFromIndex:(source.length - 4)];
NSLog(#"Last 4 Characters:%#",last4Characters);
last4Characters=nil;
Please let me know if any issue.

How to convert NData populated with hex values to NSString

I have a NSdata object that is populated with a bunch of information thats formated in hex.. I am trying to convert it into its proper string representation but am struggling to have any success.
One thing I have tried is to simply put it into a NSString and then NSLog it with a special character identifier thingy.. forgot the word (%02x), However to do this I am encoding it to NSUTF16.. which i dont want to do.. I mearly want to see exactly whats the data I am getting looks like as a NSString.
The reason I am doing this is because I am having some issues with my encoding later on in my code and im not sure if its because the data I am receiving is incorrect or me stuffing it up at some point when I am handling it.
Any help would be appreciated.
You can get a string representation of your NSData like so:
NSData *data = (your data)
NSString *string = [NSString stringWithCString:[data bytes] encoding:NSUTF8StringEncoding];
Does that answer your question?
Maybe I haven't understood, but something like this:
NSData *yourData;
NSLog(#"%#", [yourData description]);
doesn't fit your need?
Give this a try -
-(NSString*)hexToString:(NSData*)data{
NSString *hexString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
if (([hexString length] % 2) != 0)
return nil;
NSMutableString *string = [NSMutableString string];
for (NSInteger i = 0; i < [hexString length]; i += 2) {
NSString *hex = [hexString substringWithRange:NSMakeRange(i, 2)];
NSInteger decimalValue = 0;
sscanf([hex UTF8String], "%x", &decimalValue);
[string appendFormat:#"%d", decimalValue];
}
return string;
}

Decoding the scanned barcode value to int value

When I scan the barcode and I get some value if it is Equal=2 then I need to display with == and if it is Equal=3 then I need to display with = and if the value is 4 then invalid.
But Scanned Barcode are of integer value -- when decode using NSASCII it is displaying only till value 127 after that it is showing invalid results. Eg: if my Barcode value = 9699 the result value=jem then my added result value=jem= actualstring value=%åasc value id only showing 37
Here is my code:
- (void) readerView:(ZBarReaderView *)view didReadSymbols:(ZBarSymbolSet *)syms fromImage:(UIImage *)img
{
// do something useful with results -- cool thing is that you get access to the image too
for (ZBarSymbol *symbol in syms) {
[resultsBox setText:symbol.data];
if ([resultsBox.text length] == 2) {
addedresult.text = [resultsBox.text stringByAppendingString:#"=="];
} else if ([resultsBox.text length] == 3) {
addedresult.text = [resultsBox.text stringByAppendingString:#"="];
} if ([resultsBox.text length] >= 4) {
addedresult.text = #"Invalid";
}
[Base64 initialize];
NSString *myString = [[NSString alloc]initWithString:addedresult.text];
NSData * data = [Base64 decode:myString];
NSString * actualString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"%#",actualString);
labeltext.text= actualString;
int asc = [actualString characterAtIndex:0];
label.text = [NSString stringWithFormat:#"%d", asc];
[actualString release];
break;
}
}
Since someone revived this question's comments, i'll revive this entire post.
You shouldn't go through NSData to create an NSString from something you already have, and you're probably losing something along the way. Go directly to NSString using stringWithFormat. Also, ASCII will come back and byte you later, if you have a choice, use UTF8.
NSString *actualStringUTF8 = [NSString stringWithFormat:#"%#",[addedresult.text urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSString *actualStringASCII = [NSString stringWithFormat:#"%#",[addedresult.text urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"%#",actualStringUTF8);
NSLog(#"%c",[actualStringUTF8 UTF8String]); //This is a const char*
Secondly, I looked into the SDK and it says symbol.data is already an NSString*. Depending on what you want, you may not need to do anything. If you do end up needing to change encoding, make sure you understand why you need to (one good reason is "the rest of the application uses NS****StringEncoding").
Also make sure you compare strings the correct "Objective-C" way:
[actualString isEqualToString: testString];
NOT actualString == testString;

Resources