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

后端 未结 7 1113
一生所求
一生所求 2020-12-08 18:35

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.

相关标签:
7条回答
  • 2020-12-08 19:13

    In Swift Forming URL with multiple params

    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: $0)}
    
            return components.url
        }
    
    0 讨论(0)
  • 2020-12-08 19:16

    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.

    0 讨论(0)
  • 2020-12-08 19:24

    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:

    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

    0 讨论(0)
  • 2020-12-08 19:28

    Method 1

    It can add the QueryItem to your existing 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.

    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")
    
    0 讨论(0)
  • 2020-12-08 19:30
    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
    }
    
    0 讨论(0)
  • 2020-12-08 19:33

    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

    0 讨论(0)
提交回复
热议问题