Swift で日本語を含む URL を扱う
日本語を含む文字列を URL に変換する時に値が nil になることがあると思います。これは、URI において使用できない文字列を URL として変換しようとしている時に発生します。Google などの検索バーでは、このような使用できない文字列を自動でパーセントエンコーディングしているので正常に検索を行うことができます。筆者もたまに、エンコーディングを忘れてしまうのでこれを機に気をつけて行こうかと思います。
文字列をエンコード
今回は楽天市場の商品 URL を取得するという設定でエンコーディングを行っていきます。
let itemString = "スコーピオン" let itemEncodeString = itemString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) let urlString = "https://search.rakuten.co.jp/search/mall/\(itemEncodeString!)" print("itemEncodeString: \(itemEncodeString!)") // itemEncodeString: %E3%82%B9%E3%82%B3%E3%83%BC%E3%83%94%E3%82%AA%E3%83%B3 print("Result URL: \(URL(string: urlString)!.absoluteString)") // Result URL: https://search.rakuten.co.jp/search/mall/%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%94%E3%82%AA%E3%83%B3
上記のようにエンコードすることができました🎉
.addingPercentEncoding(withAllowedCharacters: CharacterSet)
にセットするCharacterSetですが、今回の場合は URL の Path にセットされる文字列に日本語が含まれている可能性があったので .urlPathAllowed
という CharacterSet を使用しています。URL String 全体に対してエンコーディングをかける場合は、.urlFragmentAllowed
もしくは .urlQueryAllowed
を使用すればそれなりに正しくは動きますが、個人的にはお勧めしません。理由としては、それぞれの CharacterSet で守備範囲としている URL コンポーネントが違うからです。例で言うと下記のように、パスの文字列で ?
を含む URL String 全体を .urlQueryAllowed
を使ってエンコードした場合、?
は文字列とみなされずエンコードされません。つまり、結果として取得した URL が正確でない可能性があります。そのため、使う用途に分けて URL コンポーネントそれぞれをエンコードするのがベストでしょう。
let urlString = "https://search.rakuten.co.jp/search/mall/スコーピオ?ン" let encodeUrlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) print("Result URL: \(URL(string: encodeUrlString!)!.absoluteString)") // Result URL: https://search.rakuten.co.jp/search/mall/%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%94%E3%82%AA?%E3%83%B3
URL コンポーネント別の CharacterSet 一覧は下記になります。