Issues displaying an emoji icon in iOS app - objective-c

I am having trouble figuring out how to get the emoji icons to display in the iPhone app I am working on. The issue is that then when someone posts something to the db from the app it gets displayed in the app as a square. What the app is getting from the server where the emojicon should be is something like this \uf604
Do anyone have any idea what I am doing wrong? I have been search for a good answer but so far I haven't found anything exactly related.
//more info
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
self.memoArray = [returnString JSONValue];
//when adding it to the label
cell.memoLabel.text = [itemData objectForKey: #"memo"];
What I have figured out is that for example '\Uf604' needs to be '\U0001F604'.

It's a bug in Json parser SBJSON. I have been using SBJson classes, in several projects, using several versions, and found some problems with complex unicodes that are used by some Emoji chars. That icons are represented with a very long unicode, I don't remember exactly the format, but it is like a double unicode. Inside SBJson I found some bugs where it parses large unicodes.
I did modify a method and it now works, but when I went to Stig's SBJson repository to inform about that, I found an open issue about unicodes: https://github.com/stig/json-framework/issues/115
Nevertheless, my solution was very different. In the version I was using, I just had to comment in the method scanUnicodeChar: all this if with its body:
/*
if (hi >= 0xd800) { // high surrogate char?
... if-body ... ...
}
*/
If your version includes that method and that 'if', try to delete it.
For other versions, perhaps the solution is as easy. Find a method named getStringToken: and inside it, inside a switch-case '\' statement, try to comment this way:
/*
if (SBStringIsSurrogateHighCharacter(hi)) {
..... body ....
} else if ....... {
.... ....
} else {
*/
CFStringAppendCharacters((CFMutableStringRef)acc, &hi, 1);
/*
}
*/
I have not tested this last one and surely something more have to be done in order to make everything work well.

Please follow following steps:
Convert Emoji characters to base64 and send to server.
On server side save base64 in database without decode.
When you want to display Emoji on Application then retrieve same base64 data from server.
Decode retrieve string and display on app.
Your Emoji character will display properly.
Note: When you want to Show on webPage then Decode data when you display data on WebPage.

Update to the latest SBJson, this issue was fixed.
https://github.com/stig/json-framework/tags

Related

Text encoding issue for NSDictionary in iOS

In my iOS app , I have Flurry SDK for analytics. Now everything is working correctly except the special symbols are not showing correctly in Flurry. tags is NSMutableArray which stores the tag for my data. It can contain alphabets , special symbols , numbers etc. Here is my code
-(void)addTestDetails
{
NSArray *array = #[#":);&;#-(-#;""-~£~¥>=#+{!|!_'",#"'%%+|*",#"TestTag",#"123:;?&",#">|€~€",#":-(/$:&"];
NSMutableDictionary *params = [[NSMutableDictionary alloc]init];
[params setObject:array forKey:#"Tags"];
[params setObject:#"test" forKey:#"Title"];
NSLog(#"params: %#",params);
}
When I debug , its showing me correct symbols without any encoding issue. Please have a look at below screenshots
But its shows as unicode as when I use NSLog below
params: {
Tags = (
":);&;#-(-#;-~\U00a3~\U00a5>=#+{!|!_'",
"'%%+|*",
TestTag,
"123:;?&",
">|\U20ac~\U20ac",
":-(/$:&"
);
Title = test;
}
I read some questions on stackoverflow regarding this issue which says its default & nothing wrong in it. If its correct , why its showing the same output in Flurry events as well when I download the data from Flurry server ? It should show me the correct symbols in there , right ? Correct me if I am wrong.
I tried using
[params setObject:[array componentsJoinedByString:#","] forKey:#"Tags"];
but still same issue.
Is there any other way I can fix this issue ?
Can anybody help me with this issue ? Thanks in advance.
Maybe it'll help
NSLog(#"%#", [NSString stringWithCString:contentString encoding:NSUTF8StringEncoding]);

Base64 encoding weirdness for iOS7 in-app purchase receipt server verification

I've found some very odd issues with base64 encoding of iOS7 receipts.
At the moment (Xcode5/iOS7) have 2 methods for getting a receipt for an in-app purchase:
Deprecated method that returns a single receipt. [SKPaymentTransaction transactionReceipt]
A bundle of all receipts from location appStoreReceiptURL
My App sells web site based services using a credit system which makes server receipt validation necessary. The App also sells downloadable extensions. So a mixture of consumables and non-consumables. The non-consumables are downloaded from Apple so no verification required. The consumables are packages of credits used for purchasing services on the website.
When iOS7 & XCode5 launched I updated my App but struggled with the new bundled receipt located at appStoreReceiptURL. With the new style, all receipts bundled in one, my server got back this error from Apple's verifyReceipt sandbox
[status] => 21002
[exception] => java.lang.IllegalArgumentException
I gave up after seening posts on stackoverflow saying others had experienced the same issue and that the opinion at the time was it was a bug, or yet to be added feature, on Apple's part.
However I've been seeing issues with using the old deprecated method which has forced me back to trying again. After a lot of debugging and searching I finally worked out some of what was going wrong - as well as getting it working but in a very ugly way which I'm not confident with going live with.
I would have thought that NSData (plain byte buffer) encoded output wouldn't differ much.
Here's the weird part I'm seeing.
The original deprecated single receipts can be base64 encode either as 64 character lines with \r\n on the end or without. Apple verification server doesn't care. It's happy either way.
For the new receipt bundle it won't work unless 2 things are done. First the base64 encoding cannot have line breaks. I notice Apple has added it's own base64 encoder into iOS7. This is what I'm using to get an encoded output that works for both receipt types.
NSString *receiptDataString = [transactionReceipt base64EncodedStringWithOptions:0];
The 2nd thing that needs to be done is to search and replace all space characters from the received encoded receipt bundle on the server. i.e.
$receiptdata = str_replace(' ', '+', $receiptdata);
I happened to noticed this was a difference between the receipts being received by my server.
Why I don't know? I'm using AFNetworking-1.3.2's JSONRequestOperationWithRequest
NSMutableArray *pairs = [[NSMutableArray alloc] initWithCapacity:0];
for (NSString *key in parameters) {
[pairs addObject:[NSString stringWithFormat:#"%#=%#", key, [parameters objectForKey:key]]];
}
postData = [[pairs componentsJoinedByString:#"&"] dataUsingEncoding:NSUTF8StringEncoding];
request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://myserver.com/index.php"]];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
Chris Prince claims to have it working with AFNetworking 2 in his reply to this question
Why could these two NSData receipts cause encoding/decoding problems like I'm seeing? I've been as detailed and clear as I can be here to help others as I see there's a lot of folks feeling the same pain here with this new receipt method Apple's introduced.
The answer turned out to be due to
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
not escaping all special characters like :/?#[]#!$&’()*+,;= etc.
The new receipt Apple provides, once base64 encoded, contains characters which need escaping but are not escaped by the above iOS lib escape encoder. Looking around I found one on here which works well. See below for working code. (Server doesn't need to parse receipt code now and can use it straight out of $_POST)
// Lifted from:
// http://stackoverflow.com/questions/2159341/nsstring-method-to-percent-escape-for-url
//
- (NSString *)urlEncodeValue:(NSString *)str {
NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR(":/?#[]#!$&’()*+,;="), kCFStringEncodingUTF8));
return result;
}
// Encode and pair basic parameters
NSMutableArray *pairs = [[NSMutableArray alloc] initWithCapacity:0];
NSString *part;
for (NSString *key in parameters) {
NSString *encodedValue = [[parameters objectForKey:key] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *encodedKey = [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
part = [NSString stringWithFormat: #"%#=%#", encodedKey, encodedValue];
[pairs addObject:part];
[pairs addObject:[NSString stringWithFormat:#"%#=%#", key, [parameters objectForKey:key]]];
}
// Receipt encoded and paired separately
receiptDataString = [self urlEncodeValue:receiptDataString];
part = [NSString stringWithFormat: #"receipt=%#", receiptDataString];
[pairs addObject:part];
// Post data.
postData = [[pairs componentsJoinedByString:#"&"] dataUsingEncoding:NSUTF8StringEncoding];

NSstream write encoding issues

Im trying to send a string using NSoutputstream , however i cant seem to get the encoding right , using dataWithContentsOfURL works
im using a nodejs TCP server with actionHero library.
it works using netcat and telnet.
- (IBAction)sendText:(id)sender {
NSString *response = [NSString stringWithFormat:#"%#", [_sendTextField.text stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSLog(#"writing %#",response);
///////////////////////////// this line works/////////////////////////////////////////////////////
// NSData *data = [[NSData alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.google.com"]]];
///////////////////////////// this line doesnt work/////////////////////////////////////////////////////
NSData *data = [[NSData alloc] initWithData:[response dataUsingEncoding:NSUTF8StringEncoding]];
//%u returns a non zero value
NSLog(#"%u",[outputStream write:[data bytes] maxLength:[data length]]);
}
i get a null streamError from handle stream Event method
Not knowing the content of response, I can't give you a specific answer as to why NSUTF8StringEncoding doesn't work with it. Generally speaking, however, if there is a byte sequence in your content that is incompatible with UTF-8, you're going to get nil when you call -dataUsingEncoding:.
There's a strategy that I learned from reading Mike Ash's blog (look under the section "Fallbacks"), and it's served me pretty well in situations such as yours.
To briefly sum it up, first try using NSUTF8StringEncoding. If that doesn't work, try using NSISOLatin1StringEncoding. And if that doesn't work, try using NSMacOSRomanStringEncoding. Mike's blog has the rationale for this.
Found the answer to my own question. turns out the problem is in actionHero's on data method where it looks for a /n which is not provided by the ios application. appended a \n and its fine now

Simple ASIHTTPRequest-based function seems to hang at upload

I've recently started trying to implement HTTP upload support to a program, but I've been having some difficulty doing so. This is the first time I've ever used objective-c (although I have a C background), so I'm still very new to the language. I've been trying to get it to work using the HTTPRequest library, but haven't been able to get anything to start working. It's a fairly large program (2500~ lines) so I won't paste it here. I'll just paste the function itself here.
- (void)Upload2HTTP2:(NSString *)ZipPath
{
[self UpdateProgressBar:#"Upload2HTTP opening Connection to Website..."];
NSLog(#"Upload2HTTP called\n");
//URL to be used to upload
NSURL *url = [NSURL URLWithString:#"http://ftp.website.com"];
NSLog(#"Upload2HTTP -%#\n",url);
//Creates the new ASIFormDataRequest object to do the uploading
//Uses the ASIHTTPRequest and ASIFormDataRequest libraries
// http://allseeing-i.com/ASIHTTPRequest/ for more information
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addRequestHeader:#"Referer" value:#"http://ftp.website.com"];
//Sets the authentication information
//This should have already been retrieved in RetrieveFromBrowser
[request setUsername:RespUID];
[request setPassword:RespPWD];
//Sets the file to be uploaded
[request setFile:ZipPath forKey:#"Customer Upload"];
//Starts the transfer?
[request startAsynchronous];
}
ZipPath, RespUID, and RespPWD are all set in another area of the program. Basically, I've got the username/PW for the HTTP authentication, and the path to the file I want to upload, but I've very little experience with the language and this library, so I'm a bit lost. I can't give any specific errors or reasons as to why it hangs, I just know that after I click upload in the program, it runs through this function, and the program hangs trying to upload the file. Is there anything I'm missing or doing wrong in this function? I'd really appreciate any help you guys could lend.
Thanks :)
ASIHTTPRequest's asynchronous networking takes advantage of the delegate design pattern. Setting the request's delegate property to self, having that class adhere to the ASIHTTPRequestDelegate protocol, and implementing - (void)requestDidFinish: and - (void)requestdidFail: should give you callbacks for finish and failure. Quick example:
- (void)Upload2HTTP2:(NSString *)ZipPath
{
...
request.delegate = self;
[request startAsynchronous];
}
- (void)requestDidFinish:(ASIHTTPRequest *)request
{
NSLog(#"Success! Do stuff here with [request responseData] or [request responseString]");
}
- (void)requestDidFail:(ASIHTTPRequest *)request
{
NSLog(#"Failure! Check out [request error] for details");
}

parsing JSON using objective C?

I have spent 1 week studying objective C. Now I am quite confused at the dealing with data part.
My friend gave me a link
http://nrj.playsoft.fr/v3/getQuiz.php?udid=23423455&app=2
and ask me write a class to parse this JSON. I had no clue what parsing JSON means. but I have gone online and looked up. I could understand a basics of it and then I impletemented a punch of code to parse this JSON. Which is:
-
(void)parseURL
{
//create new SBJSON object
SBJSON *parser = [[SBJSON alloc] init];
NSError *error = nil;
//perform request from URL
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://nrj.playsoft.fr/v3/getQuiz.php?udid=23423455&app=2"]];
// Perform request and get JSON back as a NSData object
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
// Get JSON as a NSString from NSData response
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
// parse the JSON response into an object
NSDictionary *results = [parser objectWithString:json_string error:&error];
// array just for the "answer" results
NSArray *quizes = [results objectForKey:#"quiz"];
NSDictionary *firstQuiz = [quizes objectAtIndex:0];
// finally, the name key
NSString *extract = [firstQuiz objectForKey:#"extract"];
NSLog(#"this is: %#", [extract valueForKey:#"extract"]);
}
This is at the implementation file, but in the header file I could not declare any variables, it will print out some errors. I tried to run this, there is no errors, but I am not sure this code is correct or not. And my friend asked me to write a class into an existing project. I don't know what needs to be modified and what not. I am so blur right now. Could anyone pro in this give me a hand. ?
My sincere thanks.
Thanks for reply. I have downloading and added the JSON framework ealier too. I am just not sure where to begin and where to end, meaning the step I should do when I add JSON framework into it. I could understand the syntax but I am not sure about the steps I should do. I am a newbie in this.
If you support iOS 5.0+, you should use built-in NSJSONSerialization.
It is faster than TouchJSON.
You could just use TouchJSON: http://code.google.com/p/touchcode/wiki/TouchJSON
Or you could use this one: http://code.google.com/p/json-framework/
I'm sure there are others. I use TouchJSON... it's fast and has a good API.
I recommend working through Ray Wenderlich's MapKit tutorial, especially if you are a newbie. It covers several common iOS development issues, including parsing JSON data.
http://www.raywenderlich.com/2847/introduction-to-mapkit-on-ios-tutorial
"The Implementation" section is where his JSON feed is retrieved and then in "Plotting the Data" he uses the SBJson library to parse it.