Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
104
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

@jtemplej

iOS7でのURL encode/decode

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対応は外せないのでしばらくは共存になりますね。残念です。。。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
104
Help us understand the problem. What are the problem?