为什么我不能在嵌套调用中创建url

时间:2019-11-29 15:00:35

标签: ios swift urlsession

我是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)!

具有相同的结果。

1 个答案:

答案 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和平

相关问题