如何防止命令行工具在异步操作完成之前退出

cod*_*boy 27 xcode swift2 xcode7-beta4

在swift 2命令行工具(main.swift)中,我有以下内容:

import Foundation
print("yay")

var request = HTTPTask()
request.GET("http://www.stackoverflow.com", parameters: nil, completionHandler: {(response: HTTPResponse) in
    if let err = response.error {
        print("error: \(err.localizedDescription)")
        return //also notify app of failure as needed
    }
    if let data = response.responseObject as? NSData {
        let str = NSString(data: data, encoding: NSUTF8StringEncoding)
        print("response: \(str)") //prints the HTML of the page
    }
})
Run Code Online (Sandbox Code Playgroud)

控制台显示'yay'然后退出(程序以退出代码结束:0),似乎没有等待请​​求完成.我该如何防止这种情况发生?

代码使用swiftHTTP

我想我可能需要一个NSRunLoop,但没有一个快速的例子

cod*_*boy 27

添加RunLoop.main.run()到文件末尾是一个选项.有关使用信号量的另一种方法的更多信息,请点击此处

  • Swift 4:`RunLoop.main.run()` (9认同)

skw*_*hua 14

我意识到这是一个老问题,但这是我结束的解决方案.使用DispatchGroup.

let dispatchGroup = DispatchGroup()

for someItem in items {
    dispatchGroup.enter()
    doSomeAsyncWork(item: someItem) {
        dispatchGroup.leave()
    }
}

dispatchGroup.notify(queue: DispatchQueue.main) {
    exit(EXIT_SUCCESS)
}
dispatchMain()
Run Code Online (Sandbox Code Playgroud)


Mik*_*ler 11

你可以dispatchMain()在主要结束时打电话.它运行GCD主队列调度程序并且永远不会返回,因此它将阻止主线程退出.然后,您只需要exit()在准备好时显式调用退出应用程序(否则命令行应用程序将挂起).

import Foundation

let url = URL(string:"http://www.stackoverflow.com")!
let dataTask = URLSession.shared.dataTask(with:url) { (data, response, error) in
    // handle the network response
    print("data=\(data)")
    print("response=\(response)")
    print("error=\(error)")

    // explicitly exit the program after response is handled
    exit(EXIT_SUCCESS)
}
dataTask.resume()

// Run GCD main dispatcher, this function never returns, call exit() elsewhere to quit the program or it will hang
dispatchMain()
Run Code Online (Sandbox Code Playgroud)

  • `dispatch_main()` 用于 obj-c。在 Swift 中它是 `dispatchMain()` https://developer.apple.com/documentation/dispatch/1452860-dispatchmain (2认同)

thi*_*goh 7

不要依赖时间..你应该试试这个

let sema = DispatchSemaphore( value: 0)

let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_November_2010-1a.jpg")!;

let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
  print("after image is downloaded");
  sema.signal(); // signals the process to continue
};

task.resume();
sema.wait(); // sets the process to wait
Run Code Online (Sandbox Code Playgroud)

  • [文章](https://priteshrnandgaonkar.github.io/concurrency-with-swift-3/)对我也很有用 (2认同)

Chr*_*ani 7

斯威夫特4:RunLoop.main.run()

在你的文件末尾

  • 那么它永远不会退出 (3认同)

Vex*_*exy 6

如果您的需要不是需要“生产级别”代码,而是需要一些快速实验或试用一段代码,您可以这样做:

环球银行金融电信协会3

//put at the end of your main file
RunLoop.main.run(until: Date(timeIntervalSinceNow: 15))  //will run your app for 15 seconds only
Run Code Online (Sandbox Code Playgroud)

更多信息:/sf/answers/2860911021/


请注意,您不应依赖架构中的固定执行时间。