Problem creating url - iphone

I want to create a url as below
http://maps.googleapis.com/maps/api/directions/json?origin=Adelaide,SA&destination=Adelaide,SA&waypoints=optimize:true|Barossa+Valley,SA|Clare,SA|Connawarra,SA|McLaren+Vale,SA&sensor=false
I used the following code to create this
NSURL *jsonURL;
NSString *strurl = [[NSString alloc]initWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=Adelaide,SA&destination=Adelaide,SA&waypoints=optimize:true|Barossa+Valley,SA|Clare,SA|Connawarra,SA|McLaren+Vale,SA&sensor=false"];
jsonURL = [NSURL URLWithString:strurl];
[strurl release];
NSLog(#"json Url%#",jsonURL);
NSString *jsonData = [[NSString alloc] initWithContentsOfURL:jsonURL];
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
if(jsonData == nil){
//NSLog(#"Data NIL .....");
}
else{
SBJSON *json = [[SBJSON alloc] init];
NSError *error = nil;
dic = [json objectWithString:jsonData error:&error];
[json release];
}
But every time I get jsonURL to be nil .
I think the problem is due to "|". Has someone come across same issue? If yes, can you help me out?

Try
[NSURL URLWithString:[strurl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]

The documentation for URLWithString says:
The string with which to initialize the NSURL object. Must conform to RFC 2396.
... which e.g. mentions:
Other characters are excluded because
gateways and other transport agents
are known to sometimes modify such
characters, or they are used as
delimiters.
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Data corresponding to excluded
characters must be escaped in order to
be properly represented within a URI.
Thus escape them properly as slf suggested.
Also, just use a string constant for predefined strings:
NSString *strurl = #"http://....";

As for your URL issue, Georg is right:
NSURL *jsonURL = [NSURL URLWithString:#"http://maps.googleapis.com/maps/api/directions/json?origin=Adelaide,SA&destination=Adelaide,SA&waypoints=optimize%3Atrue%7CBarossa+Valley,SA%7CClare,SA%7CConnawarra,SA%7CMcLaren+Vale,SA&sensor=false"];
Fixed that issue for me.
However, the next bit:
NSString *jsonData = [[NSString alloc] initWithContentsOfURL:jsonURL];
Is deeply troubling. You should never do synchronous data reads on the main thread. initWithContentsOfURL is going to spawn a synchronous NSURLConnection to go fetch that data and might return sometime before sunday, but you never know. (This method is ok for filesystem loads, where things are much more deterministic)
Look into an asynchronous loading API like NSURLConnection from Apple, or better yet ASIHTTPRequest, about which there is ample documentation online.
Happy webservicing!

I think, the root of cause is your string creating method.
NSString *strurl = [[NSString alloc]initWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=Adelaide,SA&destination=Adelaide,SA&waypoints=optimize:true|Barossa+Valley,SA|Clare,SA|Connawarra,SA|McLaren+Vale,SA&sensor=false"];
Try with ...
NSString *strurl = [[NSString alloc]initWithString:#"http://maps.googleapis.com/maps/api/directions/json?origin=Adelaide,SA&destination=Adelaide,SA&waypoints=optimize:true|Barossa+Valley,SA|Clare,SA|Connawarra,SA|McLaren+Vale,SA&sensor=false"];

Related

CHCSVParser - how to load from webserver

I would like to parse csv from webserver which gets updated everyday.I am using the csvparser from this link https://github.com/davedelong/CHCSVParser and I am using this code:
NSError *err = [[[NSError alloc] init] autorelease];
NSString *lunchFileURL = [[NSString stringWithFormat:#"http://www.somewhere.com/LunchSpecials.csv"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *lunchFile = [NSString stringWithContentsOfURL:[NSURL URLWithString:lunchFileURL] encoding:NSUTF8StringEncoding error:&err];
CHCSVParser *p = [[CHCSVParser alloc] initWithContentsOfCSVString:lunchFile usedEncoding:&encoding error:nil];
I get this error :
No visible #interface for 'CHCSVParser' declares the selector 'initWithContentsOfCSVString:usedEncoding:error:'
I checked this link Load remote csv into CHCSVParser and its not working .I am a noob to ios ,Please let me know how to fix this .Really Appreciate the help.Thanks in Advance.
It should probably be:
NSError *err;
NSString *lunchFileURL = [[NSString stringWithFormat:#"http://www.somewhere.com/LunchSpecials.csv"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *lunchFile = [NSString stringWithContentsOfURL:[NSURL URLWithString:lunchFileURL]
encoding:NSUTF8StringEncoding
error:&err];
// if you're going to create a CHCSVParser yourself, the syntax is:
CHCSVParser *p = [[CHCSVParser alloc] initWithCSVString:lunchFile
encoding:NSUTF8StringEncoding
error:&err];
// or, if you're going to use NSArray+CHCSVAdditions.h, the syntax might be:
NSArray *array = [[NSArray alloc] initWithContentsOfCSVString:lunchFile
encoding:NSUTF8StringEncoding
error:&err];
Note:
You don't need to alloc/init the NSError object; these classes that take a NSError ** parameter will create the autorelease error object for you if they encounter an error; otherwise they leave it alone;
The CHCSVParser class method is not initWithContentsOfCSVString, but rather initWithCSVString;
Alternatively, if you use the NSArray class extension, then the syntax is arrayWithContentsOfCSVString or initWithContentsOfCSVString; and
You specified an encoding of &encoding, but this parameter is not a pointer, so I don't see how that can possibly be right; I've just specified the encoding.
I assume you want to use the NSArray+CHCSVAdditions category method initWithContentsOfCSVString or arrayWithContentsOfCSVString (which gives you an autorelease object), not the CHCSVParser, but it's up to you.

How would i take multiple url's out of a string?

I am having my server send me a list of all the images in a certain users folder, it sends me a string and i am using SBJsonparser to get it. here is the coding:
NSString *url = [[NSString alloc]initWithFormat:#"http://mysite.com/members/grabimages.php?&username=%#", [getLogin objectAtIndex:0]];
NSString *connect = [[NSString alloc]initWithContentsOfURL:[NSURL URLWithString:url]];
SBJsonParser *parser = [[SBJsonParser alloc]init];
NSString *imagenames = [[NSString alloc]init];
imagenames = [parser objectWithString:connect error:nil];
NSLog(#"%#", imagenames);
The string returns this:
(
"./username/default/img1.jpg",
"./username/default/img2.jpg"
)
There is going to be lots of URL's in this one string at some point, i want to be able to separate all the URL's and then add each one of them into a new string.
How would i be able to do this?
Thanks :)
the error from the other post error says the object was an NSMutableArray. presumably, that object was imagenames.
if so, then you declare it like so:
NSArray *imagenames = [parser objectWithString:connect error:nil];
then you use your relative base url to compose the url, as they are relative to some directory you must know of. so, you would compose the base (as an NSURL), and use one of the -[NSURL URLByAppending... methods to create new URLs from the elements of imagenames.
You could use NSArray *array = [imagenames componentsSeparatedByString:#","]; to separate the the urls

Ampersand in POST request causing havoc

I have a simple POST coming from my iphone app. Its working fine, except passing an ampersand causes the backend to break - it's almost like its treating it like a GET request (ampersands seperate the variable names). Do I need to do some kind of encoding first? Here is the code:
NSString *content = [[NSString alloc] initWithFormat:#"data=%#&email=%#", str, emailAddress.text];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://www.myurl.com/myscript.php"]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[content dataUsingEncoding:NSISOLatin1StringEncoding]];
// generates an autoreleased NSURLConnection
[NSURLConnection connectionWithRequest:request delegate:self];
I had this issue in iOS7 and the accepted answer didn't work at all (actually, that is my standard when sending data to the backend). The ampersand was breaking in the backend side, so I had to replace the & by %26. The backend was being done in python and the code was legacy and was using ASI.
Essentially I have done the following:
NSString *dataContent = [NSString stringWithFormat:#"text=%#",
[json stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
dataContent = [dataContent stringByReplacingOccurrencesOfString:#"&"
withString:#"%26"];
ByAddingPercent....... will not work as & is a valid URL character.
I needed to send a JSON with & in it, it is the same idea though;
NSString *post = [NSString stringWithFormat:#"JSON=%#", (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)jsonString, NULL, CFSTR(":/?#[]#!$&’()*+,;="), kCFStringEncodingUTF8))];
"jsonString" towards the end is what is converted.
Edit: As stringByAddingPercentEscapesUsingEncoding: should be used to encode parts of the query, not the whole one, you should be using another method instead.
Unfortunately, Foundation doesn't provide such a method, so you need to reach to CoreFoundation:
- (NSString *)stringByURLEncodingString:(NSString *)string {
return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL, // or (__bridge CFStringRef)(#"[].")
(__bridge CFStringRef)(#":/?&=;+!##$()',*"),
kCFStringEncodingUTF8
);
}
You can use
- stringByAddingPercentEscapesUsingEncoding:
In your case it will look like this:
NSString * content = [[NSString alloc] initWithFormat:#"data=%#&email=%#", [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], [emailAddress.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
You can do this in this way, too:
NSString *dataStr = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *emailStr = [emailAddress.text stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *content = [[NSString alloc] initWithFormat:#"data=%#&email=%#", dataStr, emailStr];
I'm not sure if this will work in your case, but you could try %38 to try and encode the ampersand.

iphone: NSMutableURLRequest returns strange characters for MS Word style apostrophe

We are pulling content off our website using XML/NSMutableURLRequest and sometimes it pulls through the "curly" style apostrophe and quotes, ’ rather than '. NSMutableURLRequest seems to hate these and turns them into the strange \U00e2\U0080\U0099 string.
Is there something that I can to do prevent this? I am using the GET method, so should I be somehow telling it to use UTF-8? Or, am I missing something?
UIApplication* app = [UIApplication sharedApplication];
app.networkActivityIndicatorVisible = YES;
NSString *urlStr = [NSString stringWithFormat:#"%#",url];
NSURL *serviceUrl = [NSURL URLWithString:urlStr];
NSMutableURLRequest *serviceRequest = [NSMutableURLRequest requestWithURL:serviceUrl];
[serviceRequest setHTTPMethod:#"GET"];
NSURLResponse *serviceResponse;
NSError *serviceError;
app.networkActivityIndicatorVisible = NO;
return [NSURLConnection sendSynchronousRequest:serviceRequest returningResponse:&serviceResponse error:&serviceError];
NSURLConnection returns an NSData response. You can take that NSData response and turn it into a string. Then take this string, turn it back into a NSData object, properly UTF-8 encoding it along the way, and feed it to NSXMLParser.
Example: (Assuming response is the NSData response from your request)
// long variable names for descriptive purposes
NSString* xmlDataAsAString = [[[NSString alloc] initWithData:response] autorelease];
NSData* toFeedToXMLParser = [xmDataAsAString dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser* parser = [[[NSXMLParser alloc] initWithData:toFeedToXMLParser] autorelease];
// now utilize parser...
I would suggest replacing those characters using stringByReplacingCharactersInRange:withString: to replace the unwanted strings.
NSString *currentTitle = #"Some string with a bunch of stuff in it.";
//Create a new range for each character.
NSRange rangeOfDash = [currentTitle rangeOfString:#"character to replace"];
NSString *location = (rangeOfDash.location != NSNotFound) ? [currentTitle substringToIndex:rangeOfDash.location] : nil;
if(location){
currentTitle = [[currentTitle stringByReplacingOccurrencesOfString:location withString:#""] mutableCopy];
}
I've done this in the past to handle the same problem you describe.
Try using the stringByReplacingPercentEscapesUsingEncoding:

function to get the file name of an URL

I have some source code to get the file name of an url
for example:
http://www.google.com/a.pdf
I hope to get a.pdf
because the way to join 2 NSStrings I can get is 'appendString' which only for adding a string at right side, so I planned to check each char one by one from the right side of string 'http://www.google.com/a.pdf', when it reach at the char '/', stop the checking, return string fdp.a , after that I change fdp.a to a.pdf
source codes are below
-(NSMutableString *) getSubStringAfterH : originalString:(NSString *)s0
{
NSInteger i,l;
l=[s0 length];
NSMutableString *h=[[NSMutableString alloc] init];
NSMutableString *ttt=[[NSMutableString alloc] init ];
for(i=l-1;i>=0;i--) //check each char one by one from the right side of string 'http://www.google.com/a.pdf', when it reach at the char '/', stop
{
ttt=[s0 substringWithRange:NSMakeRange(i, 1)];
if([ttt isEqualToString:#"/"])
{
break;
}
else
{
[h appendString:ttt];
}
}
[ttt release];
NSMutableString *h1=[[[NSMutableString alloc] initWithFormat:#""] autorelease];
for (i=[h length]-1;i>=0;i--)
{
NSMutableString *t1=[[NSMutableString alloc] init ];
t1=[h substringWithRange:NSMakeRange(i, 1)];
[h1 appendString:t1];
[t1 release];
}
[h release];
return h1;
}
h1 can reuturn the coorect string a.pdf, but if it returns to the codes where it was called, after a while system reports
'double free
*** set a breakpoint in malloc_error_break to debug'
I checked a long time and foudn that if I removed the code
ttt=[s0 substringWithRange:NSMakeRange(i, 1)];
everything will be Ok (of course getSubStringAfterH can not returns the corrent result I expected.), no error reported.
I try to fix the bug a few hours, but still no clue.
Welcome any comment
Thanks
interdev
The following line does the job if url is a NSString:
NSString *filename = [url lastPathComponent];
If url is a NSURL, then the following does the job:
NSString *filename = [[url path] lastPathComponent];
Try this:
Edit: from blow comment
NSString *url = #"http://www.google.com/a.pdf";
NSArray *parts = [url componentsSeparatedByString:#"/"];
NSString *filename = [parts lastObject];
I think if you have already had the NSURL object, there is lastPathComponent method available from the iOS 4 onwards.
NSURL *url = [NSURL URLWithString:#"http://www.google.com/a.pdf"];
NSString *filename = [url lastPathComponent];
Swift 3
Let's say that your url is http://www.google.com/a.pdf
let filename = url.lastPathComponent
\\filename = "a.pdf"
This is more error free and meant for getting the localized name in the URL.
NSString *localizedName = nil;
[url getResourceValue:&localizedName forKey:NSURLLocalizedNameKey error:NULL];
I haven't tried this yet, but it seems like you might be trying to do this the hard way. The iPhone libraries have the NSURL class, and I imagine that you could simply do:
NSString *url = [NSURL URLWithString:#"http://www.google.com/a.pdf"];
NSString *path = [url path];
Definitely look for a built in function. The libraries have far more testing and will handle the edge cases better than anything you or I will write in an hour or two (generally speaking).