2008年12月21日日曜日

Cocoa(iPhone)で、日本語を含むURLを開く方法

  • 基本的にはCore FoundationのC関数を利用する
    CFURLCreateStringByAddingPercentEscapes()
  • ただし、一部問題のあるケースがある
    URL中に&を含む場合などは正しく作れないので別の方法が必要

プログラマをやっていると、だんだんと日本語が嫌いになってきます。
いや、嫌いというのはおかしいのですが、とにかく英語以外の言語はトラブルが多いです。
コンピューターというのはつくづく英語を処理するためだけに作られているのだと思います。
(だからこそ、プログラムの「国際化」で飯を食える人がいる訳ですけど!)

すみません、前置きが愚痴っぽくなってしまいました。
iPhoneプログラミングにおいてももちろん、日本語を使う際に罠があります。
たとえばNSURLRequestなどがそうです。
日本語の含まれるURLを開こうとすると、うまく解釈してくれないんです。
(といいますか日本語が含まれるURLはURLエンコードしなくちゃいけないんです。・・・当たり前ですね)

例えばこんな感じです:
http://s3.amazonaws.com/twitter_production/profile_images/65140989/るーみゃ_normal.jpeg


自分の画像だけ出ないぞ!

そこでURLエンコーディングを行う関数を探してみたところ、ありました。
Cocoaで日本語のGETを飛ばそう!

早速真似してやってみました。
CFURLCreateStringByAddingPercentEscapes()関数を使うのがポイントらしいです。
            NSString *originalUrl = [userDict objectForKey:@"profile_image_url"];
           NSString *encodedUrl = (NSString *) CFURLCreateStringByAddingPercentEscapes
           (NULL, (CFStringRef) originalUrl, NULL, NULL, kCFStringEncodingUTF8);
           person.profile_image_url = encodedUrl;

たったのこれだけでうまくいきました!



ところが、有頂天になってTwitter上で騒いでたら、
@psychsさんから突っ込みが。
JavaScriptでいうencodeURI相当なんで、
日本を適当にエスケープしたいときにはいいんだけど、
たとえばパラメタに「&」を入れたい場合とかは、
ちゃんとencodeURIComponent 相当のやつを使って組み立てなきゃだめだよ

なんと具体的なアドバイス!(ありがとうございます!)ちょっと調べてみました。
javascript: escape(), encodeURI(), encodeURIComponent() 比較

細かいところはわかりませんが、とにかく一部の文字がエンコーディングされないみたいなのです。
深刻なのは?とか=とかでしょうか。気をつけないとトラブルに巻き込まれそうですね。

ちなみにiPhoneでencodeURIComponent相当のエンコーディングを行うためにはどうすればよいのかですが、
リファレンスを引いてみても特にそれらしきものは見当たりませんでした。
ひょっとしたら自分でやるしかないかもしれません。

■2008/12/29 22:00追記
Twitter上で、@norio_nomuraさんにencodeURIComponent相当のエンコードを行う方法を教えていただきました!ありがとうございました!
http://twitter.com/norio_nomura/status/1083641557
CFURLCreateStringByAddingPercentEscapes(NULL, string, NULL, CFSTR (";,/?:@&=+$#"), kCFStringEncodingUTF8);

最大のポイントは、第4引数のCFSTRです。ここで指定した文字列はエンコードされずにそのまま残るようです。
第4引数をNULLのまま使うと標準のencodeURL相当になり、
この例のように指定すると、encodeURLComponent相当のエンコードが可能になります!