web-dev-qa-db-ja.com

Swiftの同じキーの複数の値を含むクエリパラメータでURLを作成するにはどうすればよいですか?

IOSアプリでAFNetworkingを使用しており、それが行うすべてのGETリクエストに対して、ベースURLからURLを構築し、NSDictionary Key-Valueペアを使用してパラメーターを追加します。

問題は、異なる値に対して同じキーが必要なことです。

以下に、最終的なURLが必要な例を示します。

http://example.com/.....&id=21212&id=21212&id=33232

NSDictionaryでは、同じキーに異なる値を設定することはできません。 NSSetを試しましたが、うまくいきませんでした。

let productIDSet: Set = [prodIDArray]
let paramDict = NSMutableDictionary()
paramDict.setObject(productIDSet, forKey: "id")
32
AbhishekDwivedi

必要なのはNSURLComponentsだけです。基本的な考え方は、IDのクエリアイテムの束を作成することです。プレイグラウンドに貼り付けることができるコードは次のとおりです。

import UIKit
import XCPlayground

let queryItems = [NSURLQueryItem(name: "id", value: "2121"), NSURLQueryItem(name: "id", value: "3232")]
let urlComps = NSURLComponents(string: "www.Apple.com/help")!
urlComps.queryItems = queryItems
let URL = urlComps.URL!
XCPlaygroundPage.currentPage.captureValue(URL.absoluteString, withIdentifier: "URL")

次の出力が表示されるはずです

www.Apple.com/help?id=2121&id=3232

70
Daniel Galasko

QueryItemを既存のURLに追加できます。

extension URL {

    func appending(_ queryItem: String, value: String?) -> URL {

        guard var urlComponents = URLComponents(string: absoluteString) else { return absoluteURL }

        // Create array of existing query items
        var queryItems: [URLQueryItem] = urlComponents.queryItems ??  []

        // Create query item
        let queryItem = URLQueryItem(name: queryItem, value: value)

        // Append the new query item in the existing query items array
        queryItems.append(queryItem)

        // Append updated query items array in the url component object
        urlComponents.queryItems = queryItems

        // Returns the url from new url components
        return urlComponents.url!
    }
}

使用方法

var url = URL(string: "https://www.example.com")!
let finalURL = url.appending("test", value: "123")
                  .appending("test2", value: nil)
24
Bhuvan Bhatt
func queryString(_ value: String, params: [String: String]) -> String? {    
    var components = URLComponents(string: value)
    components?.queryItems = params.map { element in URLQueryItem(name: element.key, value: element.value) }

    return components?.url?.absoluteString
}
8
Kirit Vaghela

クエリアイテムを追加するためのURL拡張。BhuvanBhattのアイデアに似ていますが、署名が異なります。

  • nilの代わりにselfを返すことで)失敗を検出できるため、たとえばURLがRFC 3986に準拠していない場合のカスタム処理が可能になります。
  • 実際にクエリ項目をパラメーターとして渡すことにより、nil値を許可します。
  • パフォーマンスのために、一度に複数のクエリアイテムを渡すことができます。
extension URL {
    /// Returns a new URL by adding the query items, or nil if the URL doesn't support it.
    /// URL must conform to RFC 3986.
    func appending(_ queryItems: [URLQueryItem]) -> URL? {
        guard var urlComponents = URLComponents(url: self, resolvingAgainstBaseURL: true) else {
            // URL is not conforming to RFC 3986 (maybe it is only conforming to RFC 1808, RFC 1738, and RFC 2732)
            return nil
        }
        // append the query items to the existing ones
        urlComponents.queryItems = (urlComponents.queryItems ?? []) + queryItems

        // return the url from new url components
        return urlComponents.url
    }
}

使用法

let url = URL(string: "https://example.com/...")!
let queryItems = [URLQueryItem(name: "id", value: nil),
                  URLQueryItem(name: "id", value: "22"),
                  URLQueryItem(name: "id", value: "33")]
let newUrl = url.appending(queryItems)!
print(newUrl)

出力:

https://example.com/...?id&id=22&id=

1
Cœur