我已经在swift中创建了一个macOS控制台应用程序,但代码永远不会被执行,=我必须使用信号量,但还有另一种方法吗? 我的目的是创建一个返回json文件的方法
class test{
func gizlo(){
let config = URLSessionConfiguration.default // Session Configuration
let session = URLSession(configuration: config) // Load configuration into Session
let url = URL(string: "https://itunes.apple.com/fr/rss/topmovies/limit=25/json")!
let task = session.dataTask(with: url, completionHandler: {
(data, response, error) in
if error != nil {
print(error!.localizedDescription)
} else {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
{
print(json)
}
} catch {
print("error in JSONSerialization")
}
}
})
task.resume()
}
}
let tr=test()
tr.gizlo()
由于
答案 0 :(得分:0)
要避免使用信号量,您可以使用等待键盘输入的简单readLine()
。是的,它不是很明显,但它是因为它阻止终端应用程序退出。
只需添加和文件:
_ = readLine()
答案 1 :(得分:0)
正如 Oleg 指出的那样,将 readLine()
放在顶级代码的末尾将阻止程序退出,直到您在终端或 Enter
指向的任何地方点击 FileHandle.standardInput
。这对于在调试器或 Playground 中快速测试代码可能没问题。无限循环也可以工作,但您必须在调试器中或从命令行使用 kill
实际终止它。
真正的问题是你为什么不想使用信号量。由于它们不难使用,我将冒险猜测这只是因为您不想用信号量污染异步数据任务完成处理程序,而您可能只需要它来等待数据进行测试目的。
假设我的猜测是正确的,真正的问题实际上并不是使用信号量,而是您认为需要将它们放置的位置。正如 David Wheeler 曾经说过的,“任何问题都可以通过添加一个间接层来解决。”
您不希望在传递给 dataTask
的完成处理程序中显式地使用信号量。因此,一种解决方案是让 gizlo
接受它自己的完成处理程序,然后创建一个调用 gizlo
的方法,并使用处理信号量的闭包。这样您就可以将两者解耦,甚至为其他用途增加一些灵活性。我已经修改了你的代码来做到这一点:
import Foundation
import Dispatch // <-- Added - using DispatchSemaphore
class test{
func gizlo(_ completion: ((Result<[String: Any]?, Error>) -> Void)? = nil) { // <-- Added externally provided completion handler
let config = URLSessionConfiguration.default // Session Configuration
let session = URLSession(configuration: config) // Load configuration into Session
let url = URL(string: "https://itunes.apple.com/fr/rss/topmovies/limit=25/json")!
let task = session.dataTask(with: url, completionHandler: {
(data, response, error) in
let result: Result<[String: Any]?, Error>
if let responseError = error { // <-- Changed to optional binding
print(responseError.localizedDescription)
result = .failure(responseError) // <-- Added this
} else {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any]
{
print(json)
result = .success(json) // <-- Added this
}
else { // <-- Added this else block
result = .success(nil)
}
} catch {
print("error in JSONSerialization")
result = .failure(error) // <-- Added this
}
}
completion?(result) // <-- Added this call
})
task.resume()
}
func blockingGizlo() throws -> [String: Any]? // <-- Added this method
{
let sem = DispatchSemaphore(value: 1)
sem.wait()
var result: Result<[String: Any]?, Error>? = nil
gizlo {
result = $0
sem.signal()
}
sem.wait() // This wait will block until the closure calls signal
sem.signal() // Release the second wait.
switch result
{
case .success(let json) : return json
case .failure(let error) : throw error
case .none: fatalError("Unreachable")
}
}
}
let tr=test()
do {
let json = try tr.blockingGizlo()
print("\(json?.description ?? "nil")")
}
catch { print("Error: \(error.localizedDescription)") }