Obtenga el valor de los parámetros de URL

81

Estoy tratando de obtener los parámetros de una URL usando Swift. Digamos que tengo la siguiente URL:

http://mysite3994.com?test1=blah&test2=blahblah

¿Cómo puedo obtener los valores de test1 y test2?

usuario2423476
fuente

Respuestas:

186

Puede usar el belowCode para obtener el parámetro

func getQueryStringParameter(url: String, param: String) -> String? {
  guard let url = URLComponents(string: url) else { return nil }
  return url.queryItems?.first(where: { $0.name == param })?.value
}

Llame al método como let test1 = getQueryStringParameter(url, param: "test1")

Otro método con extensión:

extension URL {
    public var queryParameters: [String: String]? {
        guard
            let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
            let queryItems = components.queryItems else { return nil }
        return queryItems.reduce(into: [String: String]()) { (result, item) in
            result[item.name] = item.value
        }
    }
}
Parth Adroja
fuente
¿Por qué enviar a NSURLQueryItem? Algunos innecesarios
Alexander
3
Además, es mejor usar en first(where:)lugar de filter(_:)entonces first. Se detiene tan pronto como encuentra la primera coincidencia, por lo que es mucho más rápido. Además, guarda una asignación de matriz
Alexander
1
@ user2423476 Comprobar ahora He probado en el patio de recreo con
Swift
1
@ Matian2049 Hay una biblioteca llamada "EZSwiftExtensions" que puedes usar.
Parth Adroja
1
El método de llamada corregido es: ---- let test1 = getQueryStringParameter (url: url, param: "test1")
pw2
72

Paso 1: crea una extensión de URL

extension URL {
    func valueOf(_ queryParamaterName: String) -> String? {
        guard let url = URLComponents(string: self.absoluteString) else { return nil }
        return url.queryItems?.first(where: { $0.name == queryParamaterName })?.value
    }
}

Paso 2: cómo usar la extensión

let newURL = URL(string: "http://mysite3994.com?test1=blah&test2=blahblah")!

newURL.valueOf("test1") // Output i.e "blah"
newURL.valueOf("test2") // Output i.e "blahblah"
Bhuvan Bhatt
fuente
27

También hice una extensión de URL, pero puse la búsqueda de parámetros de consulta en un subíndice.

extension URL {
    subscript(queryParam:String) -> String? {
        guard let url = URLComponents(string: self.absoluteString) else { return nil }
        return url.queryItems?.first(where: { $0.name == queryParam })?.value
    }
}

Uso:

let url = URL(string: "http://some-website.com/documents/127/?referrer=147&mode=open")!

let referrer = url["referrer"]  // "147"
let mode     = url["mode"]      // "open"
Matt Long
fuente
¡Puede usarlo así, deje urlString = URL (string: url.absoluteString)! guard let userName = urlString.valueOf ("userName"), let code = urlString.valueOf ("code"), let userId = urlString.valueOf ("userName") else {return false} print ("Detalles: (urlString)" ) print ("userName: (userName)") print ("código: (código)") print ("userId: (userId)")
Mehul
@Mehul, ¿por qué crearías una URL a partir de otra URL? No let urlString = URL(string: url.absoluteString)!tiene sentido. Por cierto URLno tiene valueOfmétodo.
Leo Dabus
9

Parece que ninguna de las respuestas existentes funciona cuando el enlace conduce a un sitio web creado en Angular. Esto se debe a que las rutas de Angular a menudo incluyen un #símbolo (hash) en todos los enlaces, lo que da como resultado que url.queryItemssiempre devuelva cero.

Si un enlace tiene este aspecto: http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah

Entonces los parámetros solo se pueden obtener de url.fragment. Con algo de lógica de análisis adicional agregada a la extensión de @ Matt, un código más universal se vería así:

extension URL {
    subscript(queryParam: String) -> String? {
        guard let url = URLComponents(string: self.absoluteString) else { return nil }
        if let parameters = url.queryItems {
            return parameters.first(where: { $0.name == queryParam })?.value
        } else if let paramPairs = url.fragment?.components(separatedBy: "?").last?.components(separatedBy: "&") {
            for pair in paramPairs where pair.contains(queryParam) {
                return pair.components(separatedBy: "=").last
            }
            return nil
        } else {
            return nil
        }
    }
}

El uso sigue siendo el mismo:

let url = URL(string: "http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah")!

let referrer = url["test1"]  // "blah"
let mode     = url["test2"]  // "blahblah"
Vitalii
fuente
Me salvaste el día al mencionar url.fragment. Muchas gracias.
Keyhan Kamangar
2

Otra forma de hacer esto es crear una extensión en la URL para devolver los componentes y luego crear una extensión en [URLQueryItem] para recuperar el valor de queryItems.

extension URL {
    var components: URLComponents? {
        return URLComponents(url: self, resolvingAgainstBaseURL: false)
    }
}

extension Array where Iterator.Element == URLQueryItem {
    subscript(_ key: String) -> String? {
        return first(where: { $0.name == key })?.value
    }
}

Y este es un ejemplo de cómo se podría usar:

if let urlComponents = URL(string: "http://mysite3994.com?test1=blah&test2=blahblah")?.components,
    let test1Value = urlComponents.queryItems?["test1"] {
    print(test1Value)
}
TotiG
fuente