问题描述
我显然遗漏了一些非常基本的/天真的/等等,但在我的一生中,我无法弄清楚如何发出简单的 GET 请求。
我正在尝试使用 Swift 5 发出 HTTP GET 请求。我查看了以下帖子/文章:one、two,但我无法获取 print()
陈述以显示任何内容。当我使用断点进行调试时,会跳过 URLSession.shared.dataTask
部分中的整个部分。
我正在查看以下代码(来自上面的第一个链接):
func HTTP_Request() {
let url = URL(string: "http://www.stackoverflow.com")!
let task = URLSession.shared.dataTask(with: url) {(data: Data?,response: URLResponse?,error: Error?) in
guard let data = data else { return }
print(String(data: data,encoding: .utf8)!)
}
task.resume()
}
HTTP_Request()
我在通过 XCode 创建的 MacOS 命令行项目中运行它。
如果我能在这方面得到任何帮助,我将不胜感激,谢谢。
解决方法
确保在退出进程之前打印响应,您可以尝试追加
RunLoop.main.run()
或
sleep(UINT32_MAX)
最后确保主线程不会退出。如果您想打印响应并立即退出进程,建议使用 DispatchSemaphore
:
let semphare = DispatchSemaphore(value: 0)
func HTTP_Request() {
let url = URL(string: "http://www.stackoverflow.com")!
let task = URLSession.shared.dataTask(with: url) {(data: Data?,response: URLResponse?,error: Error?) in
guard let data = data else { return }
print(String(data: data,encoding: .utf8)!)
semphare.signal()
}
task.resume()
}
HTTP_Request()
_ = semphare.wait(timeout: .distantFuture)
,
现在,如果出现错误,您将无声无息地失败。所以添加一些错误日志,例如,
func httpRequest() {
let url = URL(string: "https://www.stackoverflow.com")! // note,https,not http
let task = URLSession.shared.dataTask(with: url) { data,response,error in
guard
error == nil,let data = data,let string = String(data: data,encoding: .utf8)
else {
print(error ?? "Unknown error")
return
}
print(string)
}
task.resume()
}
这至少应该给你一些问题的迹象。
其他一些注意事项:
-
如果是命令行应用程序,您必须认识到该应用程序可能会在此异步网络请求完成之前退出。通常会启动一个
RunLoop
,用run(mode:before:)
循环直到网络请求完成,如run
documentation 中所述。例如,您可以为该例程提供一个完成处理程序,完成后将在主线程上调用该处理程序。然后你可以使用它:
func httpRequest(completion: @escaping () -> Void) { let url = URL(string: "https://www.stackoverflow.com")! // note,error in defer { DispatchQueue.main.async { completion() } } guard error == nil,encoding: .utf8) else { print(error ?? "Unknown error") return } print(string) } task.resume() } var finished = false httpRequest { finished = true } while !finished { RunLoop.current.run(mode: .default,before: .distantFuture) }
-
在标准 macOS 应用中,您必须在“应用沙盒”功能中启用传出(客户端)连接。
-
如果是 Playground,你必须设置
needsIndefiniteExecution
。 -
默认情况下,macOS 和 iOS 应用会禁用
http
请求,除非您在Info.plist
中启用“允许任意加载”。这不适用于命令行应用,但您应该注意如果您尝试在标准的 macOS/iOS 应用程序中执行此操作,您应该这样做。在这种情况下,您应该只使用
https
并完全避免这种考虑。
这对我有用很多次,我建议您将其摘录以备将来使用!
let url = URL(string: "https://google.com")
let task = URLSession.shared.dataTask(with: ((url ?? URL(string: "https://google.com"))!)) { [self] (data,error) in
do {
let jsonResponse = try JSONSerialization.jsonObject(with: data!,options: [])
print(jsonResponse)
guard let newValue = jsonResponse as? [String:Any] else {
print("invalid format")
}
}
catch let error {
print("Error: \(error)")
}
task.resume()
}