ios - 为什么我无法在嵌套调用尝试中创建 url

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

我想知道是否可能是无法重用的“ session ”。如能得到答复,将不胜感激。

我还使用过:

let url = URL(string: u)!

结果相同。

最佳答案

问题不在于 session (顺便说一句,您通常确实希望“重用” session ,以避免开销),而在于您如何构建 URL,特别是如何使用 URL 组件

如果您手动指定 URLComponentspath,则它需要以 / 字符开头。但是 URL 有构建带有路径的 URL 的方法:

guard let baseURL = URL(string: "https://rapport.se/api") else { ... }
let url = baseURL.appendingPathComponent(u)

这是比 URLComponents 更简单、更健壮的构建 URL 的方法。顺便说一句,这个 appendingPathComponent 通常是编写 URL 的首选方式,例如,而不是:

let url = URL(string: APIBaseUrl+"get")!

你可能会这样做:

let url = URL(string: APIBaseUrl)!.appendingPathComponent("get")

这让您不再担心“天啊,我的 APIBaseUrl 是否以 / 结尾”,特别是如果 future 程序员存在任何风险的话以删除尾部 / 的方式更改 APIBaseUrl ,突然破坏了您的代码。使用 URL 方法(如 appendingPathComponent)是实现此目的的一种可靠方法。

<小时/>

如果您想知道何时使用 URLComponents,那么如果您已有一个包含其路径的 URL,但只需将查询项添加到 URL,那么这是最有用的。例如,空格字符或 & 在包含在 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 { ... }

这将导致 URL 中的查询组件被百分比转义(即,空格被替换为 %20& 被替换为 %26):

https://example.com?q=War%20%26%20Peace

关于ios - 为什么我无法在嵌套调用尝试中创建 url,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59107095/

相关文章:

objective-c - 从另一个 ViewController 调用一个 ViewController 的实例方法

ios - KIK 卡 - 直接发送消息

ios - 未加载 Xamarin.Forms iOS 项目

iphone - iOS 上的下划线和删除线

swift - 在后台下载并在完成后唤醒应用程序

swift - 如何在显示下一个 UIViewController 之前获取 UITableView 的最后一个滚动位置?

ios - 导航栏颜色困惑

arrays - 在数组中的 UIView 上调用自定义函数

ios - swift 5 : Why is my data within struct suddenly empty/nil?

ios - Alamofire 帖子请求 :