なら@はてなブログ

福岡で働くスマートフォンエンジニア(おっさん)のブログ。更新頻度がとにかく低いのが悩み。

iOSでURLエンコード済み文字列がデコードできない場合がある

今回、iOSアプリのURLエンコード関連でちょっと気になることがあったのでエントリー。

症状としては、表題のままです。以下のURLエンコード済み文字列に対して以下のメソッドでデコードを試みた場合、きちんとデコードできずにnilが返ることがある。

- (NSString *)stringByReplacingPercentEscapesUsingEncoding:(NSStringEncoding)encoding

ぐぐってみても意外と同じような事例が見つからなかったので、文字コード変えたりしながらいろいろ試してみました。エンコード済み文字列じーっと見たり。

で、試してみると、nilになる場合はかなり限定されていて、Shift_JISエンコードした場合によく起きるみたい。
で、調べてみた。

wikipedia:URLエンコード

結論から書くと、うまくデコードできないパターンって、Wikipediaの記事を引用すると「マルチバイト文字はバイト単位で変換する。Shift_JISの2バイト目など、バイトが非予約文字に対応するなら、その文字をそのまま使用しても良い」このパターンのときです。要するに、エンコードされた文字列が、きちんと"%+16進数2桁"のみで表現されていない場合にnilが返る模様。

対策としては、いちばん簡単なのは"エンコードするときに省略形式にしない"ってことなんですが、それだとそのへんで拾ってきたエンコード済み文字列が復帰できないので、デコード時にやるとすると、「"%+3桁文字列"が見つかったら、3桁目を個別にURLエンコードして"%+16進数2桁"に変換した後で、stringByReplacingPercentEscapesUsingEncoding: を呼ぶ」ってのが正着でしょうか。あまりかっこよくないですが。

※サンプルソース書いたら後で追記します。