我是Swift和Xcode的新手,已经开始从Android移植一个小型应用程序。 没什么大不了,所以进行嵌套的api调用(像链一样)是可行的。
现在,我尝试在XCode中执行相同操作,但收到错误消息:无法构造URL。
我将为第一个起作用的代码添加代码:
func apiTest(){
/*Setting up for HTTP requests to https://example.com */
let session = URLSession.shared
let url = URL(string: APIBaseUrl+"get")!
let task = session.dataTask(with: url) { data, response, error in
if error != nil || data == nil {
print("Client error!")
return
}
guard let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) else {
print("Server error!")
return
}
guard let mime = response.mimeType, mime == "application/json" else {
print("Wrong MIME type!")
return
}
do {
let json = try JSONSerialization.jsonObject(with: data!, options: [])
print("OK?")
print(json)
let dict = json as! [String:Any]
print(dict)
print(dict["message"] ?? "Could not read response")
let expected:[String:Any] = ["message": "success"]
print(NSDictionary(dictionary: dict).isEqual(to: expected))
if(NSDictionary(dictionary: dict).isEqual(to: expected)){
//it's working
self.apiTestOk = true
/*Here: continue to a similar function*/
self.apiGetUserPrivateInfo(_id: self.id, _key: self.key)
}
//let message = json as! SimpleMessage //fel i runtime
//print (message.message) //fel i runtime
//let decoder = JSONDecoder()
//let message = try decoder.decode(SimpleMessage.self)
} catch {
print("JSON error: \(error.localizedDescription)")
}
}
task.resume()
/*end http requests*/
}
所以我用调用类似的函数
self.apiGetUserPrivateInfo(_id: self.id, _key: self.key)
该函数如下所示:
func apiGetUserPrivateInfo(_id: Int, _key: String){
//"get/userp/{id}/{key}"
let session = URLSession.shared
let u:String = APIBaseUrl+"get/userp/\(_id)/\(_key)"
print (u)
var components = URLComponents()
components.scheme = "https"
components.host = "rapport.se/api"
components.path = u
guard let url = components.url else {
preconditionFailure("Failed to construct URL") // here it fails
}
我想知道它是否可能是无法重用的“会话”。会很感激的。
我还用过:
let url = URL(string: u)!
具有相同的结果。
答案 0 :(得分:0)
问题不在于会话(顺便说一句,为了避免开销,您通常希望“重用”会话),而是如何构建URL,特别是如何使用{{1 }}。
如果您为URLComponents
手动指定path
,则必须以URLComponents
字符开头。但是/
拥有使用路径构建URL的方法:
URL
与guard let baseURL = URL(string: "https://rapport.se/api") else { ... }
let url = baseURL.appendingPathComponent(u)
相比,这是一种更简单,更可靠的URL构建方法。顺便说一句,URLComponents
通常是一般组成URL的首选方式,例如,代替:
appendingPathComponent
您可以这样做:
let url = URL(string: APIBaseUrl+"get")!
这使您摆脱了担心“天哪,我的let url = URL(string: APIBaseUrl)!.appendingPathComponent("get")
是否以APIBaseUrl
结尾”的问题,尤其是如果将来某些程序员可能会更改{{1} },以使结尾的/
被删除,从而突然破坏了代码。使用APIBaseUrl
之类的/
方法是一种可靠的方法。
如果您想知道何时使用URL
,如果您已经有了一个带有其路径的URL,但是只需要向URL添加查询项,这将是最有用的。例如,URL中包含空格字符或appendingPathComponent
时必须对其进行转义,而URLComponents
为我们做到了。考虑:
&
这将导致生成一个URL,其中查询组件将进行百分比转义(即,用URLComponents
替换空格,而用guard var components = URLComponents(string: "https://example.com") else { ... }
components.queryItems = [
URLQueryItem(name: "q", value: "War & Peace")
]
guard let url = components.url else { ... }
替换%20
的空格):
https://example.com?q=战争%20%26%20和平