Objective-C and Swift URL encoding
To escape the characters you want is a little more work.
Example code
iOS7 and above:
NSString *unescaped = @"http://www";NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];NSLog(@"escapedString: %@", escapedString);
NSLog output:
escapedString: http%3A%2F%2Fwww
The following are useful URL encoding character sets:
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}URLHostAllowedCharacterSet "#%/<>?@\^`{|}URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|}URLPathAllowedCharacterSet "#%;<>?[\]^`{|}URLQueryAllowedCharacterSet "#%<>[\]^`{|}URLUserAllowedCharacterSet "#%/:<>?@[\]^`
Creating a characterset combining all of the above:
NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];
Creating a Base64
In the case of Base64 characterset:
NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];
For Swift 3.0:
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)
For Swift 2.x:
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
Note: stringByAddingPercentEncodingWithAllowedCharacters
will also encode UTF-8 characters needing encoding.
Pre iOS7 use Core Foundation
Using Core Foundation With ARC:
NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes( NULL, (__bridge CFStringRef) unescaped, NULL, CFSTR("!*'();:@&=+$,/?%#[]\" "), kCFStringEncodingUTF8));
Using Core Foundation Without ARC:
NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes( NULL, (CFStringRef)unescaped, NULL, CFSTR("!*'();:@&=+$,/?%#[]\" "), kCFStringEncodingUTF8);
Note: -stringByAddingPercentEscapesUsingEncoding
will not produce the correct encoding, in this case it will not encode anything returning the same string.
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
encodes 14 characrters:
`#%^{}[]|\"<> plus the space character as percent escaped.
testString:
" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"
encodedString:
"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"
Note: consider if this set of characters meet your needs, if not change them as needed.
RFC 3986 characters requiring encoding (% added since it is the encoding prefix character):
"!#$&'()*+,/:;=?@[]%"
Some "unreserved characters" are additionally encoded:
"\n\r \"%-.<>\^_`{|}~"
It's called URL encoding. More here.
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding { return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", CFStringConvertNSStringEncodingToEncoding(encoding));}
This is not my solution. Someone else wrote in stackoverflow but I have forgotten how.
Somehow this solution works "well". It handles diacritic, chinese characters, and pretty much anything else.
- (NSString *) URLEncodedString { NSMutableString * output = [NSMutableString string]; const char * source = [self UTF8String]; int sourceLen = strlen(source); for (int i = 0; i < sourceLen; ++i) { const unsigned char thisChar = (const unsigned char)source[i]; if (false && thisChar == ' '){ [output appendString:@"+"]; } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || (thisChar >= 'a' && thisChar <= 'z') || (thisChar >= 'A' && thisChar <= 'Z') || (thisChar >= '0' && thisChar <= '9')) { [output appendFormat:@"%c", thisChar]; } else { [output appendFormat:@"%%%02X", thisChar]; } } return output;}
If someone would tell me who wrote this code, I'll really appreciate it. Basically he has some explanation why this encoded string will decode exactly as it wish.
I modified his solution a little. I like space to be represented with %20 rather than +. That's all.