URLSession在Linux上受支持吗?

3

当我试图在Linux上使用Swift访问牛津字典API时,遇到了障碍。可能是我的错误,但我无法确定是什么。此时,我怀疑它与基础操作系统有关。请考虑以下Bash代码:

curl -X GET --header 'Accept: text/plain' --header 'app_id: 8a7dd147' --header 'app_key: 7e7d022fbce6d8d4523eac3baa5bd04c' 'https://od-api.oxforddictionaries.com/api/v1/entries/en/ace'

这将返回Ace单词的JSON数据。现在,在Ubuntu 18.04上,我尝试执行以下操作:

import Foundation
//var request = URLRequest(url: URL(string: "https://od-api.oxforddictionaries.com/api/v1/entries/en/love")!)

// TODO: replace with your own app id and app key
let appId = "8a7dd147"
let appKey = "7e7d022fbce6d8d4523eac3baa5bd04c"
let language = "en"
let word = "Ace"
let word_id = word.lowercased() //word id is case sensitive and lowercase is required
let url = URL(string: "https://od-api.oxforddictionaries.com/api/v1/entries/en/love")!  // \(language)/\(word_id)")!
var request = URLRequest(url: url)
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(appId, forHTTPHeaderField: "app_id")
request.addValue(appKey, forHTTPHeaderField: "app_key")
//request.addValue("application/json", forHTTPHeaderField: "Content-Type")
print("passed request addValue")

let session = URLSession.shared
_ = session.dataTask(with: request, completionHandler: { data, response, error in
    if let response = response,
        let data = data,
        let jsonData = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) {
            print("about to give you a response")
        print(response)
        print(jsonData)
    } else {
        print(error)
        print(NSString.init(data: data!, encoding: String.Encoding.utf8.rawValue))
    }
}).resume()

或者以下内容:
import Foundation

let params: [String: String] = ["app_id": "8a7dd147", "app_key": "7e7d022fbce6d8d4523eac3baa5bd04c"]

var request = URLRequest(url: URL(string: "https://od-api.oxforddictionaries.com/api/v1/entries/en/love")!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("8a7dd147", forHTTPHeaderField: "app_id")
request.addValue("7e7d022fbce6d8d4523eac3baa5bd04c", forHTTPHeaderField: "app_key")

URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in
    print(response!)
    do {
        let json = try JSONSerialization.jsonObject(with: data!)
        print(json)
        print("we did it!")
    } catch {
        print("error")
    }
}).resume()

//task.resume()

但是没有返回单词“爱”的json信息。我一直在尝试调试,但无法弄清楚问题出在哪里。

  • 这是否与操作系统有关,因此是一个错误?有人能够在MacOS上进行测试吗?或者我漏掉了什么?

1
在macOS上作为单独的Swift文件尝试了一下,但是没有任何结果。当我添加了以下行sleep(10)以允许程序结束前等待10秒钟时,它就有结果了。因此,如果您将其嵌入用于创建Web服务或后端的代码中,则应尝试应用异步编程(在响应事件而不是执行其他操作时进行响应)。如果您只是制作概念验证,则可以使用Data(contentsOf:)替换URLSession以同步加载,或通过任何安全手段等待结果。 - user9335240
是的,这似乎是问题所在,我会研究一下关于API请求的异步操作,谢谢。也许你可以把你的评论转换成一个答案,这样我就可以接受了。祝一切顺利。 - lf_araujo
2个回答

4

URLSession 在后台线程上执行任务。当您结束一个多线程程序的主线程时,所有线程都会被终止(除非在某些像Java这样的语言中您可以设置守护线程,该线程可能是其他线程,但在该线程结束之后结束程序)。

因此,您的解决方案是延长主线程的生命周期,例如:

let group = DispatchGroup.init()

group.enter() // Use this before making anything that needs to be waited for
              // This manually add one to operation count in the dispatch group
URLSession.shared.dataTask(with: request, completionHandler: { data, response, error -> Void in
    defer {  // Defer makes all ends of this scope make something, here we want to leave the dispatch.
             // This is executed when the scope ends, even if with exception.


       group.leave() // Manually subtract one from the operation count
    }
    print(response!)
    do {
        let json = try JSONSerialization.jsonObject(with: data!)
        print(json)
        print("we did it!")
    } catch {
        print("error")
    }
}).resume()

group.wait()  // Wait for group to end operations.

但更好的做法是在实际应用中不阻塞主线程,例如在web应用程序中,您的应用程序通常比请求存在更长的时间,因此您不需要干涉,但要尽量避免阻塞用户(sleepDispatchGroup.wait除非在后台线程中等等...)


2
在主线程上使用 sleep() 是一个非常糟糕的想法。你的第二个想法,使用 dispatch group,要好得多。你应该编辑你的答案并删除 sleep 选项。那是错误的建议。 - Duncan C
谢谢,这对CLI工具非常有用。 - imike

0

你也可以使用这段代码:

// Avoid closing this project for 40 seconds
RunLoop.main.run(until: Date(timeIntervalSinceNow: 40))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接