Uzyskaj wartość parametrów adresu URL

81

Próbuję uzyskać parametry z adresu URL za pomocą języka Swift. Powiedzmy, że mam następujący adres URL:

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

Jak mogę uzyskać wartości test1 i test2?

user2423476
źródło

Odpowiedzi:

187

Możesz użyć poniższego kodu, aby uzyskać parametr

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
}

Wywołaj metodę, taką jak let test1 = getQueryStringParameter(url, param: "test1")

Inna metoda z rozszerzeniem:

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
źródło
Po co rzucać NSURLQueryItem? Trochę niepotrzebne
Alexander
3
Lepiej też użyć first(where:)zamiast filter(_:)wtedy first. Zatrzymuje się, gdy tylko znajdzie pierwsze dopasowanie, więc jest znacznie szybszy. Dodatkowo zapisuje alokację tablicy
Alexander
1
@ user2423476 Sprawdź teraz Testowałem na placu zabaw ze
swiftem
1
@ Matian2049 Istnieje biblioteka o nazwie „EZSwiftExtensions”, z której możesz korzystać.
Parth Adroja,
1
poprawiona metoda wywołania to: ---- let test1 = getQueryStringParameter (url: url, param: "test1")
pw2
72

Krok 1: utwórz rozszerzenie adresu 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
    }
}

Krok 2: Jak korzystać z rozszerzenia

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
źródło
27

Zrobiłem również rozszerzenie adresu URL, ale umieściłem wyszukiwanie parametrów zapytania w indeksie dolnym.

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

Stosowanie:

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
źródło
Możesz użyć w ten sposób, niech urlString = URL (string: url.absoluteString)! straż niech nazwa_użytkownika = urlString.valueOf ("nazwa_użytkownika"), let code = urlString.valueOf ("code"), let userId = urlString.valueOf ("userName") else {return false} print ("Details: (urlString)" ) print ("nazwa_użytkownika: (nazwa_użytkownika)") print ("kod: (kod)") print ("identyfikator_użytkownika: (id)")
Mehul
@Mehul, dlaczego utworzenie adresu URL z innego adresu URL let urlString = URL(string: url.absoluteString)!jest bezcelowe. Btw URLnie ma valueOfmetody.
Leo Dabus
9

Wygląda na to, że żadna z istniejących odpowiedzi nie działa, gdy odsyłacz prowadzi do witryny internetowej utworzonej w Angular. Dzieje się tak, ponieważ ścieżki Angulara często zawierają #symbol (krzyżyk) we wszystkich linkach, co powoduje, że url.queryItemszawsze zwraca zero.

Jeśli link wygląda tak: http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah

Wtedy parametry można uzyskać tylko z url.fragment. Po dodaniu dodatkowej logiki parsowania do rozszerzenia @ Matta, bardziej uniwersalny kod wyglądałby następująco:

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

Użycie pozostaje takie samo:

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
źródło
Uratowałeś mi dzień, wspominając o url.fragment. Wielkie dzięki.
Keyhan Kamangar
2

Innym sposobem na zrobienie tego jest utworzenie rozszerzenia adresu URL w celu zwrócenia komponentów, a następnie utworzenie rozszerzenia w [URLQueryItem] w celu pobrania wartości z 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
    }
}

A oto przykład, jak można to wykorzystać:

if let urlComponents = URL(string: "http://mysite3994.com?test1=blah&test2=blahblah")?.components,
    let test1Value = urlComponents.queryItems?["test1"] {
    print(test1Value)
}
totiG
źródło