Ruft den Wert der URL-Parameter ab

81

Ich versuche, die Parameter mit Swift von einer URL abzurufen. Angenommen, ich habe die folgende URL:

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

Wie kann ich die Werte von test1 und test2 erhalten?

user2423476
quelle

Antworten:

186

Sie können den folgenden Code verwenden, um den Parameter abzurufen

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
}

Nennen Sie die Methode wie let test1 = getQueryStringParameter(url, param: "test1")

Andere Methode mit Erweiterung:

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
quelle
Warum besetzen NSURLQueryItem? Einige unnötig
Alexander
3
Außerdem ist es besser zu nutzen , first(where:)anstatt filter(_:)dann first. Es stoppt, sobald es das erste Match findet, also ist es viel schneller. Außerdem spart es eine Array-Zuordnung
Alexander
1
@ user2423476 Jetzt prüfen Ich habe auf dem Spielplatz mit Swift 3 getestet.
Parth Adroja
1
@ Matian2049 Es gibt eine Bibliothek namens "EZSwiftExtensions", die Sie verwenden können.
Parth Adroja
1
Die korrigierte Aufrufmethode lautet: ---- let test1 = getQueryStringParameter (URL: URL, Parameter: "Test1")
pw2
72

Schritt 1: URL-Erweiterung erstellen

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

Schritt 2: Verwendung der Erweiterung

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
quelle
26

Ich habe auch eine URL-Erweiterung erstellt, aber die Suche nach Abfrageparametern in einen Index eingefügt.

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

Verwendung:

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
quelle
Sie können dies verwenden, lassen Sie urlString = URL (Zeichenfolge: url.absoluteString)! Wächter let userName = urlString.valueOf ("userName"), let code = urlString.valueOf ("code"), let userId = urlString.valueOf ("userName") else {return false} print ("Details: (urlString)" ) print ("Benutzername: (Benutzername)") print ("Code: (Code)") print ("Benutzer-ID: (Benutzer-ID)")
Mehul
@Mehul, warum Sie eine URL aus einer anderen URL erstellen würden, let urlString = URL(string: url.absoluteString)!ist sinnlos. Übrigens URLhat keine valueOfMethode.
Leo Dabus
9

Es scheint, dass keine der vorhandenen Antworten funktioniert, wenn der Link zu einer auf Angular erstellten Website führt. Dies liegt daran, dass Angulars Pfade häufig ein #(Hash-) Symbol in allen Links enthalten, was dazu führt, dass url.queryItemsimmer Null zurückgegeben wird.

Wenn ein Link so aussieht: http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah

Dann können die Parameter nur von erhalten werden url.fragment. Mit einer zusätzlichen Parsing-Logik zur Erweiterung von @ Matt würde ein universellerer Code folgendermaßen aussehen:

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

Die Nutzung bleibt gleich:

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
quelle
Sie haben meinen Tag gerettet, indem Sie url.fragment erwähnt haben. Vielen Dank.
Keyhan Kamangar
2

Eine andere Möglichkeit besteht darin, eine Erweiterung für die URL zu erstellen, um die Komponenten zurückzugeben, und anschließend eine Erweiterung für [URLQueryItem] zu erstellen, um den Wert aus den queryItems abzurufen.

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

Und dies ist ein Beispiel dafür, wie dies verwendet werden könnte:

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