带参数的Swift GET请求 [英] Swift GET request with parameters

查看:126
本文介绍了带参数的Swift GET请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对swift很陌生,所以我的代码中可能会有很多错误,但我试图实现的是发送 GET 请求到一个带有参数的本地主机服务器。更重要的是我试图实现它,因为我的函数有两个参数 baseURL:string,params:NSDictionary 。我不知道如何将这两个结合到实际的URLRequest中?这是我到目前为止所尝试的结果

  func sendRequest(url:String,params:NSDictionary){
let urls :NSURL! = NSURL(string:url)
var request = NSMutableURLRequest(URL:url)
request.HTTPMethod =GET
var data:NSData! = NSKeyedArchiver.archivedDataWithRootObject(params)
request.HTTPBody = data
println(request)
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request,completionHandler :loadedData)
task.resume()




func loadedData(data:NSData!,response:NSURLResponse! ,err:NSError!){
if(err!= nil){
println(err?.description)
} else {
var jsonResult:NSDictionary = NSJSONSerialization.JSONObjectWithData数据,选项:NSJSONReadingOptions.MutableContainers,error:nil)as NSDictionary
println(jsonResult)



$ b code >


解决方案

在构建 GET 请求时,这个请求没有任何内容,而是一切都在URL上。要构建一个URL(并正确转换百分比),您还可以使用 URLComponents

  var url = URLComponents(string:https://www.google.com/search/)! 
$ b $ url.queryItems = [
URLQueryItem(name:q,value:War& Peace)
]

唯一的技巧是大多数Web服务需要 + 字符百分比转义(因为他们会解释作为 <$ c $所规定的空格字符c> application / x-www-form-urlencoded specification )。但 URLComponents 不会百分比转义它。 Apple争辩说, + 是查询中的有效字符,因此不应该转义。从技术上讲,它们是正确的,它允许在一个URI的查询中,但它在 application / x-www-form-urlencoded 请求中有特殊含义,并且确实应该苹果公司承认我们必须转换字符数<%c $ c> + ,但建议我们做它手动:

  var url = URLComponents(string:https://www.wolframalpha.com/input/)! 

url.queryItems = [
URLQueryItem(name:i,value:1 + 2)
]

url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of:+,with:%2B)

是一个不起眼的解决方法,但它是有效的,并且是Apple建议的,如果您的查询可能包含一个 + 字符并且您有一个服务器将它们解释为空格。 p>

因此,将它和你的 sendRequest 例程结合起来,就可以得到如下结果:

  func sendRequest(_ url:String,parameters:[String:String],completion:@escaping([String:Any]?,Error?) - >无效){
var components = URLComponents(string:url)!
components.queryItems = parameters.map {(key,value)in
URLQueryItem(name:key,value:value)
}
components.percentEncodedQuery = components.percentEncodedQuery ?.用以下代码替换事件:(+,用:%2B)
let request = URLRequest(url:components.url!)

let task = URLSession.shared.dataTask请求){数据,响应,错误
guard让data = data,//是否有数据
let response = response as? HTTPURLResponse,//有HTTP响应
(200 ..< 300)〜= response.statusCode,//是statusCode 2XX
错误== nil else {//在那里没有错误,否则。 ..
完成(无,错误)
返回
}

让responseObject =(try?JSONSerialization.jsonObject(with:data))as? [String:Any]
completion(responseObject,nil)
}
task.resume()
}

你可以这样称呼它:

  sendRequest(someurl ,参数:[foo:bar]){responseObject,错误
guard let responseObject = responseObject,error == nil else {
print(error ??Unknown error)
return
}

//在这里使用`responseObject`
}

就我个人而言,现在我会使用 JSONDecoder ,并返回一个自定义的 struct 而不是字典,但这不是真的有关。希望这可以说明如何将参数编码到GET请求的URL中的基本思想。

href =https://stackoverflow.com/revisions/27724627/13>以前版本的这个答案为Swift 2和手动转义百分比。


I'm very new to swift, so I will probably have a lot of faults in my code but what I'm trying to achieve is send a GET request to a localhost server with paramters. More so I'm trying to achieve it given my function take two parameters baseURL:string,params:NSDictionary. I am not sure how to combine those two into the actual URLRequest ? Here is what I have tried so far

    func sendRequest(url:String,params:NSDictionary){
       let urls: NSURL! = NSURL(string:url)
       var request = NSMutableURLRequest(URL:urls)
       request.HTTPMethod = "GET"
       var data:NSData! =  NSKeyedArchiver.archivedDataWithRootObject(params)
       request.HTTPBody = data
       println(request)
       var session = NSURLSession.sharedSession()
       var task = session.dataTaskWithRequest(request, completionHandler:loadedData)
       task.resume()

    }

}

func loadedData(data:NSData!,response:NSURLResponse!,err:NSError!){
    if(err != nil){
        println(err?.description)
    }else{
        var jsonResult: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
        println(jsonResult)

    }

}

解决方案

When building a GET request, there is no body to the request, but rather everything goes on the URL. To build a URL (and properly percent escaping it), you can also use URLComponents.

var url = URLComponents(string: "https://www.google.com/search/")!

url.queryItems = [
    URLQueryItem(name: "q", value: "War & Peace")
]

The only trick is that most web services need + character percent escaped (because they'll interpret that as a space character as dictated by the application/x-www-form-urlencoded specification). But URLComponents will not percent escape it. Apple contends that + is a valid character in a query and therefore shouldn't be escaped. Technically, they are correct, that it is allowed in a query of a URI, but it has a special meaning in application/x-www-form-urlencoded requests and really should not be passed unescaped.

Apple acknowledges that we have to percent escaping the + characters, but advises that we do it manually:

var url = URLComponents(string: "https://www.wolframalpha.com/input/")!

url.queryItems = [
    URLQueryItem(name: "i", value: "1+2")
]

url.percentEncodedQuery = url.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")

This is an inelegant work-around, but it works, and is what Apple advises if your queries may include a + character and you have a server that interprets them as spaces.

So, combining that with your sendRequest routine, you end up with something like:

func sendRequest(_ url: String, parameters: [String: String], completion: @escaping ([String: Any]?, Error?) -> Void) {
    var components = URLComponents(string: url)!
    components.queryItems = parameters.map { (key, value) in 
        URLQueryItem(name: key, value: value) 
    }
    components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
    let request = URLRequest(url: components.url!)

    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data,                            // is there data
            let response = response as? HTTPURLResponse,  // is there HTTP response
            (200 ..< 300) ~= response.statusCode,         // is statusCode 2XX
            error == nil else {                           // was there no error, otherwise ...
                completion(nil, error)
                return
        }

        let responseObject = (try? JSONSerialization.jsonObject(with: data)) as? [String: Any]
        completion(responseObject, nil)
    }
    task.resume()
}

And you'd call it like:

sendRequest("someurl", parameters: ["foo": "bar"]) { responseObject, error in
    guard let responseObject = responseObject, error == nil else {
        print(error ?? "Unknown error")
        return
    }

    // use `responseObject` here
}

Personally, I'd use JSONDecoder nowadays and return a custom struct rather than a dictionary, but that's not really relevant here. Hopefully this illustrates the basic idea of how to percent encode the parameters into the URL of a GET request.


See previous revision of this answer for Swift 2 and manual percent escaping renditions.

这篇关于带参数的Swift GET请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆