ios issue with stringByAddingPercentEscapesUsingEncoding - ios

In my app I need to send some parameters to the url, when I am trying with the stringByAddingPercentEscapesUsingEncoding it is not converting correctly. If I am not using this encoding I am getting null(Exception) from the nsurl.Here is me code.
http://www.mycompurl.co?message=xyz&id=____ here I am sending the id 1 or 2 or any number.
when I convert this string to url by using stringByAddingPercentEscapesUsingEncoding I got
"http://www.mycompurl.co?message=xyz&id=**%E2%80%8B**1" (when I send 1 as parameter). Then I got the 0 data from the Url.
str = [NSString stringWithFormat:#"%#?message=xyz&id=​%#",Application_URL,bootupdateNew];
str = [str stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
url=[NSURL URLWithString:str];
NSError* error = nil;
data1 = [NSData dataWithContentsOfURL:url options:NSDataReadingUncached error:&error];
Thank you In advance

Basics
A URL is composed of several components.
Each component has its own rule how the component's source string must be encoded, so that this component becomes valid within the URL string.
Applying stringByAddingPercentEscapesUsingEncoding: will never always produce a correct URL if the string consists of more than one component (and if we assume, we have an unbounded set of source strings - so that the encoded string actually differs from the source string).
It even won't work always with a string which represents any single component.
In other words, for what's worth, stringByAddingPercentEscapesUsingEncoding: should not be used to try to make a URL out of several components. Even getting the URL query component correctly encoded is at least error prone, and when utilizing stringByAddingPercentEscapesUsingEncoding: it still remains wonky. (You may find correct implementations on SO, though - and I posted one myself).
But now, just forget about it:
It took awhile for Apple to recognize this failure, and invented NSURLComponents. It's available since iOS 7. Take a look! ;)

Related

split string in ios string from json data?

I have one string. Now I wanted to split this string. For static separation I know the code but I don’t code for dynamic value.
my string is
NSString *str = #"https://graph.facebook.com/v2.5/181054825200000/feed?fields=created_time,message,picture,full_picture,comments.limit%280%29.summary%28true%29,likes.limit%280%29.summary%28true%29&limit=5&format=json&access_token=CAALjFrE5mNYBAOg1EDiUrsE2kr1kIRrLIv7g4OweSMvHso2exB5Dttshn7dgOlW24ZCXSnDZAWiV6xMUKXedTXUhiHpdmZBPCGzD1orFlrLRP2gaBZCbZBZBnjUHewF9hZBmJKxtiwVzpw9gnnQXk5Hfx0ZBM2ksAUzkSWR5feaNMbf3UUmUpJlxeh0gKdDrzWBvIJRPy0xGqL0ZAMFsRhyCZCTX42l1sZAceZB0VCeDZB95mrAZDZD&until=1456345291&__paging_token=enc_AdCKD3tSYMoZB3MCKaJkYnbVmBgUyY2tBceGDD2G1hqxRDiQKZCsSbmvWZASLvlCMf0BVzq2uZAScSWp7ZAavZB2d72BIHJISefk09noRuv9gA5b5hFwZDZD";
but i don’t how to show any value dynamically .(for e.g. until (in string))
please help me for this issue.
Thank You.
If you are parsing a URL you should really use NSURLComponents. It makes breaking a URL into the different parts much easier, and the code is tested and verified by Apple.
For separate string by a separator you can use this.
NSString *url = #"<url>";
NSArray *array = [url componentsSeparatedByString:#"<seperator string>"];
NSLog(#"%#", array);
But for URL parsing ,As per Duncan's answer, yes it is good to parse a URL using NSURLComponents. By using this class you can get any desired part of an URL.

Determining Issue With Retrieving JSON from URL in iPhone

Let me start off by saying that I am not particularly trying to find a solution, just the root cause of the problem. I am trying to retrieve a JSON from a url. In browser, the url call works just fine and I am able to see the entire JSON without issue. However, in x-code when simply using NSURLConnection, I am getting data bytes, but my NSString is null.
theString = [[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding];
After doing some research I have found that I am probably trying to use the wrong encoding. I am not sure what type of encoding is being used by the url, so on first instinct I just tried some random encoding types.
NSString* myString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSString* myString2 = [[NSString alloc] initWithData:data encoding:NSUTF16StringEncoding];
NSString* myString3 = [[NSString alloc] initWithData:data encoding:NSWindowsCP1252StringEncoding];
NSASCIIStringEncoding and NSWindowsCP1252StringEncoding is able to bring back a partially correct JSON. It is not the entire JSON thatI am able to view in the browser, and some characters are a little messed up, but it is something. To try and better determine what encoding was used, I decided to use the following method to try and determine it by looking at what encoding returned.
NSError *error = nil;
NSStringEncoding encoding;
NSString *my_string = [[NSString alloc] initWithContentsOfURL:url
usedEncoding:&encoding
error:&error];
My NSStringEncoding value is 3221214344. And this number is consistent everytime I run the app. I can not find any NSStringEncoding values that even come close to matching this.
My final question is: Is the encoding used for this url not consumable by iOS, is it possible that multiple types of encoding was used for this url, or is there something else that I could be doing wrong on my end?
It's best not to rely on Cocoa to figure out the string encoding if possible, especially if the data might be corrupted. A better approach would be to check if the value indicated by the HTTP Content-Type header specifies a character set like in this example:
Content-Type: text/html; charset=ISO-8859-4
Once you're able to parse and retrieve a character set name from the Content-Type header, you need to convert it to an NSStringEncoding, first by passing it to CFStringConvertIANACharSetNameToEncoding, and then passing the returned CF string encoding to CFStringConvertEncodingToNSStringEncoding. After that, you can initialize your string using -[NSString initWithData:encoding:].
NSData *HTTPResponseBody = …; // Get the HTTP response body
NSString *charSetName = …; // Get a charset name from the Content-Type HTTP header
// Get the Core Foundation string encoding
CFStringEncoding cfencoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)charSetName);
// Confirm this is a known encoding
if (cfencoding != kCFStringEncodingInvalidId) {
// Initialize the string
NSStringEncoding nsencoding = CFStringConvertEncodingToNSStringEncoding(cfencoding);
NSString *JSON = [[NSString alloc] initWithData: HTTPResponseBody
encoding: nsencoding];
}
You still may run into problems if the string data you're working with is corrupted. For example, in the above code snippet, perhaps charSetName is UTF-8, but HTTPResponseBody can't be parsed as UTF-8 because there's an invalid byte sequence. In this situation, Cocoa will return nil when you try to instantiate your string, and short of sanitizing the data so that it conforms to the reported string encoding (perhaps by stripping out invalid byte sequences), you may want to report an error back to the end user.
As a last-ditch effort — rather than reporting an error — you could initialize a string using an encoding that can handle anything you throw at it, such as NSMacOSRomanStringEncoding. The one caveat here is that unicode / corrupted data may show up intermittently as symbols or unexpected alphanumerics.
Even though it seems that the answer has been provided in the comments (using iso-8859-1 as the correct encoding) I thought it worthwhile to discuss how I would go about debugging this problem.
You said that the Desktop Browser (Chrome) can digest the data correctly, so let's use that:
Enable Developer Tools https://developers.google.com/chrome-developer-tools/
When the Dev Tools window is open, switch to "network" and execute your call in that browser tab
check the output by clicking on the request url - it should give you some clue.
If that doesn't work, tools like Postman can help you to recreate the call before you implement it on the device

Get request length limit in iOS

I am using Omniture SiteCatalyst in my iPhone app.It uses get request to hit the servers internally via its sdk.However i am facing an issue where some of the request are not reaching the Omniture servers.The get request which is being sent is of variable length depending on the type of request(around 900 + characters).
My question is whether there any limit for the get request length in an iOS app? and if yes
how it would behave in case the request crosses the limit?
Theoretically if URL conforms to RFC 2396 it is fine. According to documentation
The NSURL class fails to create a new NSURL object if the path being
passed is not well-formed; the path must comply with RFC 2396.
Examples of cases that will not succeed are strings containing space
characters and high-bit characters. Should creating an NSURL object
fail, the creation methods return nil, which you must be prepared to
handle. If you are creating NSURL objects using file system paths, you
should use fileURLWithPath: or initFileURLWithPath:, which handle the
subtle differences between URL paths and file system paths. If you
wish to be tolerant of malformed path strings, you’ll need to use
functions provided by the Core Foundation framework to clean up the
strings.
But some time there is issue with specail character e.g. space, accents and others. You must [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
It is also possible server could not handle very long urls, if there are any limitation on server, server will simple truncate the rest of url string, if this is an issue then server will return 414 error url too long.

%2C URL causing iOS app crash

I have an iOS application which downloads a JSON feed from this URL:
https://www.googleapis.com/youtube/v3/activities?part=snippet%2CcontentDetails&home=true&maxResults=50&access_token=%#
I am storing the URL in a NSString for later use. I am also adding a NSString to the end of the URL which contains an access token which I am using for OAuth Authentication (hence the %# at the very end of the URL).
Here is how I am storing the URL:
NSString *pre_yt_user_url = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/activities?part=snippet%2CcontentDetails&home=true&maxResults=50&access_token=%#", token_youtube];
As you can see part of the URL has a %2C
This is causing a warning and making my iOS app to crash!!
Here are the warning I get:
Format specifies type 'unsigned-short' but the argument has type NSString
and:
More % conversions than data arguments
What am I doing wrong here? Can't I store a URL in a string??
Thanks, Dan.
When using stringWithFormat the % character is the start of a data argument unless it's escaped. So you need to escape it because you don't want to use it as a supplied parameter. You need to use %%2C (because the first % escapes the second %).

Getting NSData from a url works in the simulator but not on a device

I implement a method that send notes to the server:
-(IBAction)inserttotextfied:(id)sender{
NSString *strurl=[NSString stringWithFormat:#"http://localhost/get-data/insert.php?Name=%#&message=%#",txtf.text,txt2.text];
NSData *dataurl=[NSData dataWithContentsOfURL:[NSURL URLWithString:strurl]];
NSString *stresult=[[[NSString alloc]initWithData:dataurl encoding:NSUTF8StringEncoding]autorelease];
NSLog(#"%a",stresult);
}
The problem is when I test it via simulator the is being sent, but when I test it in the device the data did not being saved
You probably don't want to send something to localhost on your device, or do you use a different url on the device build?
Simulator is faster in response. So the url return data and print properly. But on device the response time is higher then simulator. Your NSLog(#"%a",stresult); statement is executing before it get any data from the response. I will suggest to give some delay or use delegate so that you can use data after getting the response.
Format Specifier %a is 64-bit floating-point number (double), printed in scientific notation with a leading 0x and one hexadecimal digit before the decimal point using a lowercase p to introduce the exponent.
if that is not your intent, try this:
NSLog(#"%#", stresult);

Resources