やりたいこと
Swift で URL のクエリストリングを簡単に追加したい
例)"https://qiita.com"
-> "https://qiita.com?name=value"
環境
Swift 4.0
冗長になりやすい
Swift では文字列結合やURLComponents
を利用することでクエリストリングの追加が可能ですが、いずれも冗長な書き方となってしまいます。
- 文字列結合を行う場合
let url = URL(string: "https://qiita.com")!
let queryStringAddedUrl = URL(string:
url.description.description + (nil == url.query ? "?" : "&") + "name=value"
) // https://qiita.com?name=value
-
URLComponents
を使用する場合
let url = URL(string: "https://qiita.com")!
var components = URLComponents(url: url, resolvingAgainstBaseURL: nil != url.baseURL)
components?.queryItems = [URLQueryItem(name: "name", value: "value")] + (components?.queryItems ?? [])
let queryStringAddedUrl = components?.url // https://qiita.com?name=value
簡潔にしてみた
簡潔に書きたかったのでURL
に Extension を実装しました。
URL+.swift
extension URL {
// クエリを一つ追加した新しいURLを返す
func queryItemAdded(name: String, value: String?) -> URL? {
return self.queryItemsAdded([URLQueryItem(name: name, value: value)])
}
// クエリを複数追加した新しいURLを返す
func queryItemsAdded(_ queryItems: [URLQueryItem]) -> URL? {
guard var components = URLComponents(url: self, resolvingAgainstBaseURL: nil != self.baseURL) else {
return nil
}
components.queryItems = queryItems + (components.queryItems ?? [])
return components.url
}
}
使ってみるとこうなります。シンプルです。
let queryStringAddedUrl = url.queryItemAdded(name: "name", value: "value") // https://qiita.com?name=value
これだと困ること
- 同一キーなクエリを追加する必要がある場合
-
String?
以外の型のまま追加したくなる場合
にはこれだけだと対応が難しいです。上の Extension を拡張していくのも良いですが、ググるとURLQueryBuilderのようなライブラリがあるので手を出してみるのもいいかもしれません。