POST 在命令行应用中 Swift 使用 URLSession 请求

POST Request with URLSession in Swift in command line app

我正在尝试在命令行应用程序中使用 POST 方法发送 HTTP 请求。使用 JSON 作为请求的正文。我正在使用 session.uploadTask 发送此请求并使用从简单 Dictionary 序列化的 JSON 数据。也许我错过了什么,但它不起作用。我什至尝试将我的请求写入控制台,它看起来不错 -> 它与 iTranslate API 想要的格式相同。

//creating new session
let session = URLSession.shared
let url = URL(string: "https://api.itranslate.com/translate/v1")!

//setting httpMethod to POST
var request = URLRequest(url: url)
request.httpMethod = "POST"

//setting header
request.setValue("application/json", forHTTPHeaderField: "content-type")

//dictionary with json
let json = ["key": "...", "source": ["dialect":"en", "text": "How are you?"], "target": ["dialect": "es"]] as [String : Any]

//serialization from json to jsonData
let jsonData = try! JSONSerialization.data(withJSONObject: json, options: [])

let task = session.uploadTask(with: request, from: jsonData) { data, response, error in
    
    if let data = data, let dataString = String(data: data, encoding: .utf8) {
        print(dataString)
    }
}

task.resume()

在大多数应用程序中,有一个“运行 循环”不断 运行ning,响应用户交互,使应用程序保持活动状态,直到用户明确终止它。在那种情况下,我们可以启动异步网络请求,确信 运行 循环使我们的应用程序保持活动状态,并且当网络响应到来时,我们的完成处理程序闭包被调用。

另一方面,在命令行应用程序中,当它到达代码末尾时,应用程序会简单地终止,从不给异步网络请求响应的机会,并且永远不会调用闭包。

但是,您可以让命令行应用在终止之前等待请求完成,例如

let semaphore = DispatchSemaphore(value: 0)

let task = session.uploadTask(with: request, from: jsonData) { data, response, error in
    if let data = data, let dataString = String(data: data, encoding: .utf8) {
        print(dataString)
    }
    semaphore.signal()
}

task.resume()
semaphore.wait()

现在,这种技术(在主线程上等待,从而阻塞该线程)在标准应用程序中是一种非常糟糕的做法,因为它会在网络请求 运行ning 时阻塞主线程。在典型的应用程序中,阻塞主线程会冻结 UI,提供不合标准的用户体验(OS 甚至可能会因为没有响应而终止应用程序)。我们一般不会阻塞主线程。

但是在命令行应用程序中,您通常不必担心优雅和响应迅速 UI,阻塞主线程不是什么大问题,上面的内容可以让应用程序在网络连接时保持活动状态请求是 运行ning.