所以,我有一个Swift命令行程序:
import Foundation
print("start")
startAsyncNetworkingStuff()
RunLoop.current.run()
print("end")
代码编译没有错误。异步网络代码运行得很好,获取其所有数据,打印结果,并最终调用其完成功能。
如何让完成功能突破当前的runloop以便最后一个"结束"得到印刷?
添加了:
使用以下内容替换RunLoop.current.run():
print("start")
var shouldKeepRunning = true
startAsyncNetworkingStuff()
let runLoop = RunLoop.current
while ( shouldKeepRunning
&& runLoop.run(mode: .defaultRunLoopMode,
before: .distantFuture ) ) {
}
print("end")
设置
shouldKeepRunning = false
异步网络完成功能中的仍然不会导致"结束"打印。 (这是通过将带有print语句的shouldKeepRunning = false语句括起来进行检查的,这些语句实际上是打印到控制台)。缺少什么?
答案 0 :(得分:9)
对于命令行界面,请使用此模式并向 AsyncNetworkingStuff 添加完成处理程序(感谢Rob提供代码改进):
print("start")
let runLoop = CFRunLoopGetCurrent()
startAsyncNetworkingStuff() { result in
CFRunLoopStop(runLoop)
}
CFRunLoopRun()
print("end")
exit(EXIT_SUCCESS)
请不要使用丑陋的while
循环。
答案 1 :(得分:1)
(回答我自己的问题)
将以下代码段添加到我的异步网络完成代码中,可以打印“结束”:
DispatchQueue.main.async {
shouldKeepRunning = false
}
答案 2 :(得分:1)
以下是使用Swift 4.2在macOS命令行工具中使用URLSession
的方法
// Mac Command Line Tool with Async Wait and Exit
import Cocoa
// Store a reference to the current run loop
let runLoop = CFRunLoopGetCurrent()
// Create a background task to load a webpage
let url = URL(string: "http://SuperEasyApps.com")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let data = data {
print("Loaded: \(data) bytes")
}
// Stop the saved run loop
CFRunLoopStop(runLoop)
}
task.resume()
// Start run loop after work has been started
print("start")
CFRunLoopRun()
print("end") // End will print after the run loop is stopped
// If your command line tool finished return success,
// otherwise return EXIT_FAILURE
exit(EXIT_SUCCESS)
您必须在开始之前使用对运行循环的引用来调用stop函数(如上所示),或者使用GCD才能按预期退出。
func stopRunLoop() {
DispatchQueue.main.async {
CFRunLoopStop(CFRunLoopGetCurrent())
}
}
参考
https://developer.apple.com/documentation/corefoundation/1542011-cfrunlooprun
运行循环可以递归运行。您可以从任何运行循环调用中调用CFRunLoopRun(),并在当前线程的调用堆栈上创建嵌套的运行循环激活。
https://developer.apple.com/documentation/corefoundation/1541796-cfrunloopstop
如果运行循环嵌套有一个激活从另一个激活开始的标注,则仅退出最内部的激活。