My function takes a dictionary argument and a variadic number of NSString variables. All this combined is put in an [NSString stringWithFormat:] method, and is returned as a NSURLRequest. The method looks like this:
- (NSURLRequest *)buildPath:(NSString *)stringPath attributes:(NSString *)attribute, ...
{
va_list list;
NSString *eachObject;
NSMutableArray *args = [NSMutableArray array];
[args addObject:attribute];
va_start(list, attribute);
while ((eachObject = va_arg(list, NSString *))) {
[args addObject:eachObject];
}
va_end(list);
NSString *listOfAttributes = [args componentsJoinedByString:#", "];
NSString *pathURL = _requestString[stringPath];
NSString *path = [NSString stringWithFormat:pathURL, listOfAttributes];
NSURL *url = [NSURL URLWithString:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
return request;
}
This is what it looks like when I call the method:
NSURLRequest *request = [_venueService buildPath:#"categories"
attributes:_venueService.clientID, _venueService.clientSecret, _venueService.todaysDate, nil];
When I run the program, it crashes. When I log out listOfAttributes it gives me:
client_id, client_secret, 20140507
This is my 3 arguments, which is correct, and the stringPath (when I actually call it in my program I write stringPath[#"categories"]) which, when I NSLog gives me:
https://api.foursquare.com/v2/venues/categories?client_id=%#&client_secret=%#&v=%#
So, my question is, why would these two strings, combined in an [NSString stringWithFormat:] cause problems?
Any help would be greatly appreciated!
As Justin pointed out, there is a much simpler way of doing this. NSString has a -initWithFormat:arguments: method that does exactly what you want.
Also, your method name has a few issues:
Naming convention - you should indicate in the method name its purpose (creating a URL request)
You are passing in an (NSDictionary *) for the path, but casting it to an (NSString *) when you use it. The two objects are not type compatible. I'm supposing this might be a typo when you copy-pasted your code?
Might as well use the same calling convention as NSString's +stringWithFormat: method.
Given all of the above, the method becomes something like (without error checking):
- (NSURLRequest *)URLRequestWithFormat:(NSString *)format, ... {
va_list arguments;
va_start(arguments, format);
NSString *urlPath = [[NSString alloc] initWithFormat:format arguments:arguments];
va_end(arguments);
NSURL *url = [NSURL URLWithString:urlPath];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
return request;
}
This worked fine with a call like:
NSURLRequest *request = [self URLRequestWithFormat:#"https://api.foursquare.com/v2/venues/categories/client_id=%#&client_secret=%#&v=%#", #"One",#"Two",#"Three"];
NSLog(#"Request: %#", request);
With output:
2014-05-07 09:52:30.645 Test[5888:60b] Request: <NSURLRequest: 0x8c64f30> { URL: https://api.foursquare.com/v2/venues/categories/client_id=One&client_secret=Two&v=Three }
You may want to read the documentation for -[NSString initWithFormat:arguments:]. That method accepts a va_list parameter and will probably do what you want.
The reason your sample code doesn't work is because stringWithFormat needs a separate argument for each placeholder that appears in the format string. Your format string looks like it contains three %# placeholders, but you're only passing one argument, listOfAttributes.
The format within stringPath is specifying that there should be 3 arguments, but you are only supplying one - listOfAttributes.
listOfAttributes is one argument not 3.
Related
I want to create a global variable which is part of a URL, which will be created on run time using a string from the user.
For example:
#define base_URL #"http://api.openweathermap.org/data/2.5/find?q=%#&unit=metrics"
also please suggest how should I use it, for example:
NSString *url = [NSString stringWithFormat:#"%#%#", base_URL, string.text];
You could simply do the following having NSString *input:
NSString *url = [NSString stringWithFormat:base_URL, input];
This will replace %# with the string from input
From my point of view you've got 2 options
Store the variable on a Plist and read it every time you need it
Create a singleton which contains the variable
I'd go with 1, but that's a personal choice
Did you try with this one?
#define BASE_URL(__ARGS__) [NSString stringWithFormat: #"YOUR_URL%#", __ARGS__]
You can use it as:
NSURL *url = [NSURL urlWithString: BASE_URL(string.text)];
You can use the method
- (NSString *)stringByReplacingOccurrencesOfString:(NSString *)target
withString:(NSString *)replacement
Example
#define URL #"This is %# Url"
NSString *newStr = [URL stringByReplacingOccurrencesOfString:#"%#" withString:#"Hello"];
I have url that I am going to request data from. Here is the code.
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:urlStr]];
This works except when I have certain characters such as ş. The urlstr will return null. Is there a way around this to except certain character types? Any tips or suggestions are appreciated.
I've used the following method with success in many applications:
- (NSString *)urlEncode:(NSString *)str {
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)str, NULL, CFSTR("!*'();:#&=+$,/?%#[]"), kCFStringEncodingUTF8));
}
Note that I use this on only the params of the URL, so the following would work (notice I added the ş, which seemed to work, although I'm not familiar with that character):
NSString *baseURL = #"http://www.google.com";
NSString *paramsString = #"testKey=test value_with some (weirdness)!___ş";
NSString *resultingURLString = [NSString stringWithFormat:#"%#?%#", baseURL, [self urlEncode:paramsString]];
Which produces the result:
http://www.google.com?testKey%3Dtest%20value_with%20some%20%28weirdness%29%21___%C5%9F
I've got a small problem that seems a little bit odd to me. I often used NSString or NSLog while adding NSNumbers into several places:
NSNumber *categoryId = [[NSNumber alloc]initWithInt:0];
NSURL *url = [NSURL URLWithString:#"http://shop.rs/api/json.php?action=getCategoryByCategory&category=%i",[categoryId integerValue]];
Now xcode tells me that I'm too many arguments. What am I doing wrong? Setting up an NSNumber into NSStrings or NSLogs works as I did it above.
Best Regards
What is wrong is on
NSURL *url = [NSURL URLWithString:#"http://shop.rs/api/json.php?action=getCategoryByCategory&category=%i",[categoryId integerValue]];
you are calling URLWithString: and then pass in a string that is not being formatted correctly. If you want to do it all on one line then you need to be using stringWithFormat: like
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://shop.rs/api/json.php?action=getCategoryByCategory&category=%i",[categoryId integerValue]]];
Because it is adding a parameter you can't just create a string like you normally would with #"some text" you need to format it using the stringWithFormat: which will return an NSString * with the text held within #"" and the paramters you pass in. So [NSString stringWithFormat:#"My String will come with %#", #"Apples"]; this would provide an NSString with "My String will come with Apples". For more information check out the Apple Documentation for NSString and stringWithFormat:
Try this :
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://shop.rs/api/json.phpaction=getCategoryByCategory&category=%i", [categoryId integerValue]]];
Initially code was wrong because of : "categoryId integerValue]" (I forgot a '[').
You can use NSString to form your NSURL. You can then pass it to your URLWithString like below:
NSNumber *categoryId = [NSNumber numberWithInteger:0];
NSString *urlString = [NSString stringWithFormat:#"http://shop.rs/api/json.php?action=getCategoryByCategory&category=%i",[categoryId integerValue]];
NSURL *url = [NSURL URLWithString:urlString];
I have a URL like myApp://action/1?parameter=2&secondparameter=3&thirdparameter=10
I need to change parameter = 2
and secondparameter =3 like myApp://action/1?parameter=10&secondparameter=15&thirdparameter=10
Any ideas
Thx a lot
NSString *myURL
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
NSString * parameter =#"2";
NSString * secondparameter =#"3";
myURL =[[NSString alloc] initWithFormat:#"myApp://action/1?parameter=%#&secondparameter=%#&thirdparameter=10",parameter,secondparameter];
}
else
{
NSString * parameter =#"10";
NSString * secondparameter =#"15";
myURL =[[NSString alloc] initWithFormat:#"myApp://action/1?parameter=%#&secondparameter=%#&thirdparameter=10",parameter,secondparameter];
}
NSURL *url = [NSURL URLWithString:myURL];
Try this code...
You're saying you need to perform this on an arbitrary URL, so the steps are:
Break the query down into something you can work with, i.e. a dictionary
Mutate the query dictionary
Construct a new URL with the new query
I maintain the KSFileUtilities repository. The KSURLQueryUtilities routines will help you easily achieve the above.
I am getting this error: [NSURL stringByAppendingFormat:]: unrecognized selector sent to instance 0x5869210 when it gets to the append. strcust is a plain number and strURI is correct until the append.
NSString *strUIR = [NSURL URLWithString:#"https://cid.hooru.mobi:36610/?";
strURI = [strURI stringByAppendingFormat:#&Cust=IPRR%#", strCust];
Any thoughts would be appreciated. I am just trying to append Name/value pairs from variables. Can't get the append to work.
There are several problems with this piece of code:
You're declaring an NSString but you are assigning an NSURL
You're missing a right square bracket ']'
You're missing a double quote on your second line
You're trying to call an NSString method on an NSURL object
You're misspelling strURI on your first line (it is strUIR)
Try this:
NSString *strURI = #"https://cid.hooru.mobi:36610/?";
strURI = [strURI stringByAppendingFormat:#"&Cust=IPRR%d", strCust];
//Note the %d (if strCust is an int. If it's an NSString use %#)
NSURL *myUrl = [NSURL UrlWithString:strURI];
[NSURL URLWithString:] returns pointer of type NSURL. Merely collecting the return value that is NSURL* type in NSString* type does not convert it to NSString* type. Therefore strUIR is NSURL* type, even though declared as NSString strUIR, and hence you cannot pass any message to strUIR that is supposed to be passed to NSString type.
NSURL doesn't respond to stringByAppendingFormat:
You specify strURI as an NSString so the compiler won't raise a warning, but you set it to an NSURL.
Either initialize the full string before creating the NSURL, or use URLByAppendingPathComponent:, I would recommend the first option.
NSString *path = #"https://cid.hooru.mobi:36610/?"
...
path = [path stringByAppendingFormat:#"&Cust=IPRR%#", strCust];
NSURL *url = [NSURL URLWithString:path]
For more information, see the docs: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/Reference/Reference.html