How can I build a URL with query parameters contai

2020-02-08 09:42发布

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.

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 -

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.

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

8条回答
成全新的幸福
2楼-- · 2020-02-08 10:10

All you need is NSURLComponents. The basic idea is to create a bunch of query items for your id's. Here's code you can paste into a playground:

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")

You should see an output of

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

查看更多
乱世女痞
3楼-- · 2020-02-08 10:11

2019

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") }
}

Percent-encoding and everything else is handled.

查看更多
We Are One
4楼-- · 2020-02-08 10:12
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
}
查看更多
叼着烟拽天下
5楼-- · 2020-02-08 10:15

Extending on the extension ideas above, this was more useful in my case:

extension URL {
    func appendParameters( params: Parameters) -> URL? {
        var components = URLComponents(string: self.absoluteString)
        components?.queryItems = params.map { element in URLQueryItem(name: element.key, value: element.value as? String) }
        return components?.url
    }
}

USAGE:

let queryParams: [String: String] = [
        "search": "top repos",
        "returnCount": "10"
]

let api = "https://api.github.com"
let url = URL(string: api)?.appendParameters(params: queryParams)

RESULT:

https://api.github.com?search=top%20repos&returnCount=10
查看更多
看我几分像从前
6楼-- · 2020-02-08 10:22

I guess u just have to do something like this:

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

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

查看更多
Bombasti
7楼-- · 2020-02-08 10:30

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

  • it can detect failures (by returning nil instead 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.
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

查看更多
登录 后发表回答