記事を書くに至った動機
URLのパラメーターを取得する際に
URLComponentsとinitializer内の第二引数のresolvingAgainstBaseURLは何だろうと気になった為、記事にしました。
init?(
url: URL,
resolvingAgainstBaseURL resolve: Bool
)
URLComponentとは
カスタムURLをスキームを利用した際に、
struct URLComponents
URLComponents を使用することで、URLを安全に組み立てたり分解したりすることが可能になります。
下記のように
init?(string URLString: String)
Stringから初期化してもいいのですが、
URLであることが保証されるresolvingAgainstBaseURL付きのイニシャライザを利用した方が安全かと思います。
resolvingAgainstBaseURLについて
本題ですが、
resolvingAgainstBaseURLをtrueにすると相対URLを絶対URLに変換する試みが行われます。
具体的にtrueの場合とfalseの場合の違いを見ていきます。
trueの場合
相対URLであれば、それをベースURLに対して解決し絶対URLを生成します。
if let baseURL = URL(string: "https://example.com/directory/"),
let relativeURL = URL(string: "subdirectory/file", relativeTo: baseURL),
let urlComponents = URLComponents(url: relativeURL, resolvingAgainstBaseURL: true) {
print(urlComponents.url?.absoluteString ?? "Invalid URL")
}
// 出力: https://example.com/directory/subdirectory/file
falseの場合
falseにするとURLはそのまま使用され、ベースURLに対して相対URLを解決しません。
if let baseURL = URL(string: "https://example.com/directory/"),
let relativeURL = URL(string: "subdirectory/file", relativeTo: baseURL),
let urlComponents = URLComponents(url: relativeURL, resolvingAgainstBaseURL: false) {
print(urlComponents.url?.absoluteString ?? "Invalid URL")
}
// 出力: subdirectory/file
実際のアプリでの使い方
実用的な使い方としてurlからパラメーターを取得するコードを載せます。
let urlString = "https://example.com/path?param1=value1¶m2=value2"
// パラメーター名だけ取得したい場合
if let url = URL(string: urlString), let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) {
let queryItemNames = urlComponents.queryItems?.map { $0.name } ?? []
print(queryItemNames)
} else {
print("Invalid URL")
}
// パラメーター名と値両方をreduceして取得したい場合
if let url = URL(string: urlString), let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false) {
let queryItems = urlComponents.queryItems ?? []
let parameters = queryItems.reduce(into: [String: String]()) { (result, item) in
result[item.name] = item.value
}
print(parameters)
} else {
print("Invalid URL")
}
参照