Reputation: 5998
I am currently trying to put together an URL where I specify some GET parameters. But I want to use japanese or other characters too in this URL.
Is there a way to convert a NSString to a string containing the HTML entities for the 'special' characters in my NSString?
I am currently using the following code, which seems to work, except for 'special characters' like chinese and japanese:
NSString* url = @"/translate_a/t?client=t&sl=auto&tl=";
url = [url stringByAppendingString:destinationLanguage];
url = [url stringByAppendingString:@"&text="];
url = [url stringByAppendingString:text];
NSURL* nsurl = [[NSURL alloc] initWithScheme:@"http" host:@"translate.google.com" path:url];
NSError* error;
NSString* returnValue = [[NSString alloc] initWithContentsOfURL:nsurl encoding:NSUTF8StringEncoding error:&error];
Upvotes: 3
Views: 6454
Reputation: 2973
For simple URL encoding of strings, many of the solutions I have seen, while technically correct, look a lot less easy to use than I would like. So I came up with the following NSString category:
@interface NSString (MLExtensions)
- (NSString *)urlencode;
@end
NSString *_mlfilterChars = @";/?:@&=+$,";
@implementation NSString (MLExtensions)
- (NSString *)urlencode
{
return [[NSString stringWithString: (NSString *)
CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)self,
NULL,
(CFStringRef)_mlfilterChars,
kCFStringEncodingUTF8)]
stringByReplacingOccurrencesOfString: @"%20" withString: @"+"];
}
@end
I'm kind of in a hurry with some other stuff I'm working on, so I kind of cheated with the %20 => + conversion step, but it all seems to work great and I've been using it for a while now with a good number of URLs in my app.
Usage is blessfully easy:
- (NSString *)URLForSearch: (NSString *)searchFor
{
return [@"http://example.org/search?query="
stringByAppendingString: [searchFor urlencode]];
}
Upvotes: 0
Reputation: 9982
To properly URL encode your parameters, you need to convert each name and value to UTF-8, then URL encode each name and value separately, then join names with values using '=' and name-value pairs using '&'.
I generally find it easier to put all the parameters in an NSDictionary, then build the query string from the dictionary. Here's a category that I use for doing that:
// file NSDictionary+UrlEncoding.h
#import <Cocoa/Cocoa.h>
@interface NSDictionary (UrlEncoding)
-(NSString*) urlEncodedString;
@end
// file NSDictionary+UrlEncoding.m
#import "NSDictionary+UrlEncoding.h"
// private helper function to convert any object to its string representation
static NSString *toString(id object) {
return [NSString stringWithFormat: @"%@", object];
}
// private helper function to convert string to UTF-8 and URL encode it
static NSString *urlEncode(id object) {
NSString *string = toString(object);
return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}
@implementation NSDictionary (UrlEncoding)
-(NSString*) urlEncodedString {
NSMutableArray *parts = [NSMutableArray array];
for (id key in self) {
id value = [self objectForKey: key];
NSString *part = [NSString stringWithFormat: @"%@=%@",
urlEncode(key), urlEncode(value)];
[parts addObject: part];
}
return [parts componentsJoinedByString: @"&"];
}
@end
The method build an array of name-value pairs called parts
by URL encoding each key and value, then joining them together with '='. Then the parts in the parts
array are joined together with '&' characters.
So for your example:
#import "NSDictionary+UrlEncoding.h"
// ...
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
[parameters setValue: @"t" forKey: @"client"];
[parameters setValue: @"auto" forKey: @"sl"];
[parameters setValue: destinationLanguage forKey: @"tl"];
[parameters setValue: text forKey: @"text"];
NSString *urlString = [@"/translate_a/t?" stringByAppendingString: [parameters urlEncodedString]];
Upvotes: 4
Reputation: 4198
Here's NSString extension you can find over internet
The decode part has some error in mapping array index to actual entity number. But since you only need encoding, it's fine to use it.
Upvotes: 1