iOS7以前は標準でそれっぽいメソッドが用意されてますが、これが意図してない感じで動いてくれます。
使えないパターン
NSString* targetString = @"http://hogehoge.com/?param=!*'();:@&=+$,/?%#[]";
// encode
NSString* encodeString = [targetString
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// decode
NSString* decodeString = [encodeString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// なんか違うよねこれ
NSLog(@"encode %@", encodeString); // http://hogehoge.com/param=!*'();:@&=+$,/?%25%23%5B%5D
だから開発者は皆ブログなどからこれじゃないかという解決策を見つけカテゴリーに実装します。
頑張ったパターン
// カテゴリ追加して独自で頑張る
@interface NSString(Url)
-(NSString*) urlEncode;
-(NSString*) urlDecode;
@end
@implementation NSString(Url)
-(NSString*) urlEncode {
return (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)self,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8));
}
-(NSString*) urlDecode {
return (NSString *)CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(
kCFAllocatorDefault,
(__bridge CFStringRef)self,
CFSTR(""),
kCFStringEncodingUTF8));
}
@end
// 実際に動かしてみる
NSString* targetString = @"http://hogehoge.com/?param=!*'();:@&=+$,/?%#[]";
NSString* encodeString = [targetString urlEncode];
NSString* decodeString = [encodeString urlDecode];
// あら?いい感じ
NSLog(@"encode %@", encodeString); // http%3A%2F%2Fhogehoge.com%2F%3Fparam%3D%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%25%23%5B%5D
まぁこれでいいんですが、iOS7からこのように独自で実装しなくてもいいメソッドが追加されたので
せっかくならそれ使って少しでも楽しようぜってのが今回の内容です。
iOS7からNSStringのカテゴリに
- (NSString *)stringByAddingPercentEncodingWithAllowedCharacters:(NSCharacterSet *)allowedCharacters
- (NSString *)stringByRemovingPercentEncoding
の2個が追加されてます。
これを使用して上記処理を置き換えてみましょう。
iOS7版
NSString* targetString = @"http://hogehoge.com/?param=!*'();:@&=+$,/?%#[]";
NSString* encodeString = [targetString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet alphanumericCharacterSet]];
NSString* decodeString = [encodeString stringByRemovingPercentEncoding];
// あら?カテゴリ実装しなくてもいい感じ
NSLog(@"encode %@", encodeString); // http%3A%2F%2Fhogehoge%2Ecom%2F%3Fparam%3D%21%2A%27%28%29%3B%3A%40%26%3D%2B%24%2C%2F%3F%25%23%5B%5D
とほぼ同じ結果になります。
encodeする文字列をカスタマイズしたい場合は引数で渡してるNSCharacterSetを変更すればいいだけですし
こちらの方が何となくおしゃれな感じがしますね。
ただ、現状iOS6対応は外せないのでしばらくは共存になりますね。残念です。。。