Nhận giá trị của Tham số URL


81

Tôi đang cố gắng lấy các tham số từ một URL bằng Swift. Giả sử tôi có URL sau:

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

Làm cách nào để lấy giá trị của test1 và test2?

Câu trả lời:


186

Bạn có thể sử dụng Mã bên dưới để lấy tham số

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
}

Gọi phương thức như let test1 = getQueryStringParameter(url, param: "test1")

Phương pháp khác có phần mở rộng:

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

Tại sao chuyển sang NSURLQueryItem? Một số không cần thiết
Alexander

3
Ngoài ra, tốt hơn là sử dụng first(where:)thay vì filter(_:)sau đó first. Nó dừng ngay khi tìm thấy trận đấu đầu tiên, vì vậy nó nhanh hơn nhiều. Thêm vào đó, nó tiết kiệm phân bổ mảng
Alexander

1
@ user2423476 Kiểm tra bây giờ tôi đã thử nghiệm ở sân chơi với nhanh chóng 3.
Parth Adroja

1
@ Matian2049 Có một thư viện tên là "EZSwiftExtensions" bạn có thể sử dụng nó.
Parth Adroja

1
phương thức gọi đã sửa là: ---- let test1 = getQueryStringParameter (url: url, param: "test1")
pw2

72

Bước 1: Tạo tiện ích mở rộng 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
    }
}

Bước 2: Cách sử dụng tiện ích mở rộng

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"

27

Tôi cũng đã tạo một phần mở rộng URL, nhưng đặt tra cứu tham số truy vấn vào một chỉ số con.

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

Sử dụng:

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

let referrer = url["referrer"]  // "147"
let mode     = url["mode"]      // "open"

Bạn có thể sử dụng như thế này, hãy 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 ("Chi tiết: (urlString)" ) print ("userName: (userName)") print ("code: (code)") print ("userId: (userId)")
Mehul

@Mehul tại sao bạn tạo URL từ một URL khác let urlString = URL(string: url.absoluteString)!là vô nghĩa. Btw URLkhông có valueOfphương pháp.
Leo Dabus

9

Có vẻ như không có câu trả lời hiện có nào hoạt động khi liên kết dẫn đến một trang web được tạo trên Angular. Điều này là do các đường dẫn của Angular thường bao gồm #ký hiệu (băm) trong tất cả các liên kết, điều này dẫn đến việc url.queryItemsluôn trả về con số không.

Nếu một liên kết giống như thế này: http://example.com/path/#/morepath/aaa?test1=blah&test2=blahblah

Sau đó, các tham số chỉ có thể được lấy từ url.fragment. Với một số logic phân tích cú pháp bổ sung được thêm vào tiện ích mở rộng của @ Matt, một mã phổ quát hơn sẽ giống như sau:

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

Cách sử dụng vẫn như cũ:

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

let referrer = url["test1"]  // "blah"
let mode     = url["test2"]  // "blahblah"

Bạn đã cứu ngày của tôi bằng cách đề cập đến url.fragment. Cảm ơn rất nhiều.
Keyhan Kamangar

2

Một cách khác để thực hiện việc này là tạo tiện ích mở rộng trên URL để trả về các thành phần, rồi tạo tiện ích mở rộng trên [URLQueryItem] để truy xuất giá trị từ 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
    }
}

Và đây là một ví dụ về cách có thể sử dụng điều này:

if let urlComponents = URL(string: "http://mysite3994.com?test1=blah&test2=blahblah")?.components,
    let test1Value = urlComponents.queryItems?["test1"] {
    print(test1Value)
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.