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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31944011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 07:39:48  来源:igfitidea点击:

How to prevent a Command Line Tool from exiting before asynchronous operation completes

xcodeswift2xcode7-beta4

提问by codecowboy

In a swift 2 command line tool (main.swift), I have the following:

在 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
    }
})

The console shows 'yay' and then exits (Program ended with exit code: 0), seemingly without ever waiting for the request to complete. How would I prevent this from happening?

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

The code is using swiftHTTP

代码使用的是swiftHTTP

I think I might need an NSRunLoopbut there is no swift example

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

采纳答案by skwashua

I realize this is an old question, but here is the solution I ended on. Using DispatchGroup.

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

let dispatchGroup = DispatchGroup()

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

dispatchGroup.notify(queue: DispatchQueue.main) {
    exit(EXIT_SUCCESS)
}
dispatchMain()

回答by codecowboy

Adding RunLoop.main.run()to the end of the file is one option. More info on another approach using a semaphore here

添加RunLoop.main.run()到文件末尾是一种选择。有关使用信号量的另一种方法的更多信息here

回答by Mike Vosseller

You can call dispatchMain()at the end of main. That runs the GCD main queue dispatcher and never returns so it will prevent the main thread from exiting. Then you just need to explicitly call exit()to exit the application when you are ready (otherwise the command line app will hang).

您可以dispatchMain()在 main 的末尾调用。它运行 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()

回答by thiagoh

Don't depend on timing.. You should try this

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

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")

  // signals the process to continue
  sema.signal()
}

task.resume()

// sets the process to wait
sema.wait()

回答by Vexy

If your need isn'tsomething that requires "production level" code but some quick experiment or a tryout of a piece of code, you can do it like this :

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

SWIFT 3

斯威夫特 3

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

More info : https://stackoverflow.com/a/40870157/469614

更多信息:https: //stackoverflow.com/a/40870157/469614



Please notethat you shouldn't rely on fixed execution time in your architecture.

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

回答by Chris Karani

Swift 4: RunLoop.main.run()

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

At the end of your file

在您的文件末尾