ios 如何在 Swift 中使用包含多个值的查询参数构建 URL?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34060754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:19:57  来源:igfitidea点击:

How can I build a URL with query parameters containing multiple values for the same key in Swift?

iosswiftswift2nsurl

提问by AbhishekDwivedi

I am using AFNetworking in my iOS app and for all the GET requests it makes, I build the url from a base URL and than add parameters using NSDictionary Key-Value pairs.

我在我的 iOS 应用程序中使用 AFNetworking,对于它发出的所有 GET 请求,我从基本 URL 构建 URL,然后使用 NSDictionary 键值对添加参数。

The problem is that I need same key for different values.

问题是我需要不同值的相同键。

Here is an example of what I need the finally URL to look like -

这是我需要最终 URL 的示例 -

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

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

It's not possible in NSDictionary to have different values in same keys. So I tried NSSet but did not work.

在 NSDictionary 中不可能在相同的键中具有不同的值。所以我尝试了 NSSet 但没有奏效。

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

回答by Daniel Galasko

All you need is URLComponents(or NSURLComponents in Obj-C). The basic idea is to create a bunch of query items for your id's. Here's code you can paste into a playground:

您只需要URLComponents(或 Obj-C 中的 NSURLComponents)。基本思想是为您的 id 创建一堆查询项。以下是您可以粘贴到 Playground 中的代码:

import Foundation
import XCPlayground

let queryItems = [URLQueryItem(name: "id", value: "1"), URLQueryItem(name: "id", value: "2")]
var urlComps = URLComponents(string: "www.apple.com/help")!
urlComps.queryItems = queryItems
let result = urlComps.url!
print(result)

You should see an output of

你应该看到输出

www.apple.com/help?id=1&id=2

www.apple.com/help?id=1&id=2

回答by Bhuvan Bhatt

Method 1

方法一

It can add the QueryItemto your existing URL.

它可以将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!
    }
}

How to use

如何使用

var url = URL(string: "https://www.example.com")!
let finalURL = url.appending("test", value: "123")
                  .appending("test2", value: nil)

Method 2

方法二

In this method, the URL will be updated automatically.

在此方法中,URL 将自动更新。

extension URL {

    mutating func appendQueryItem(name: String, value: String?) {

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

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

        // Create query item
        let queryItem = URLQueryItem(name: name, 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
        self = urlComponents.url!
    }
}

// How to use
var url = URL(string: "https://www.example.com")!
url.appendQueryItem(name: "name", value: "bhuvan")

回答by Kirit Vaghela

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
}

回答by C?ur

An URL extension to append query items, similar to Bhuvan Bhatt idea, but with a different signature:

附加查询项的 URL 扩展,类似于 Bhuvan Bhatt 的想法,但具有不同的签名:

  • it can detect failures (by returning nilinstead of self), thus allowing custom handling of cases where the URL is not RFC 3986 compliant for instance.
  • it allows nil values, by actually passing any query items as parameters.
  • for performance, it allows passing multiple query items at a time.
  • 它可以检测失败(通过返回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
    }
}

Usage

用法

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)

Output:

输出:

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

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

回答by Wasim

In Swift Forming URL with multiple params

在具有多个参数的 Swift Forming URL 中

func rateConversionURL(with array: [String]) -> URL? {
            var components = URLComponents()
            components.scheme = "https"
            components.host = "example.com"
            components.path = "/hello/"
            components.queryItems = array.map { URLQueryItem(name: "value", value: 
private func tellServerSomething(_ d: String, _ s: String) {

    var c = URLComponents(string: "https://you.com/info")
    c?.queryItems = [
        URLQueryItem(name: "description", value: d),
        URLQueryItem(name: "summary", value: s)
    ]
    guard let u = c?.url else { return print("url fail") }
    do {
        let r = try String(contentsOf: u)
        print("Server response \(r)")
    }
    catch { return print("comms fail") }
}
)} return components.url }

回答by Fattie

2019

2019年

let params = ["id" : [1, 2, 3, 4], ...];

Percent-encoding and everything else is handled.

处理百分比编码和其他所有内容。

回答by Serg Dort

I guess u just have to do something like this:

我想你只需要做这样的事情:

##代码##

which will be encoded into: ....id%5B%5D=1&id%5B%5D=2&id%5B%5D=3&id%5B%5D=4....

它将被编码为:....id%5B%5D=1&id%5B%5D=2&id%5B%5D=3&id%5B%5D=4....