I am writing a command line application in Swift using a third-party framework that (if I understand the code correctly) relies on GCD callbacks to complete certain actions when a socket receives data. In order to better understand the framework, I have been playing around with a sample Cocoa application the framework's author wrote to go along with the framework.
Because the sample application is a Cocoa application, the run loops are handled automatically. I'm including snippets of code from the sample application (MIT license) to give an idea of how it works:
class AppDelegate: NSObject, NSApplicationDelegate {
var httpd : Connect!
func startServer() {
httpd = Connect()
.onLog {
[weak self] in // unowned makes this crash
self!.log($0)
}
.useQueue(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))
...
httpd.listen(1337)
}
...
func applicationDidFinishLaunching(aNotification: NSNotification?) {
startServer()
...
}
}
I'd like to modify the sample application to run from the command line. When I put the startServer() function into a command line application, it runs, but the socket is immediately closed after it is opened, and the program finishes executing with an exit code 0. This is expected behavior, as there are no run loops in an Xcode command line project, and thus the program doesn't know to wait for the socket to receive data.
I believe the correct way to get the socket to stay open and the program to continuously run would be to put the main thread in a CFRunLoop. I have looked over Apple's documentation and, except for the basic API reference, there is nothing on threading in Swift. I have looked at third party resources, but they all involve alternate threads in iOS and Cocoa applications. How do I properly implement a CFRunLoop for the main thread?
async
-await
. You need it with asynchronous completion handler or delegate patterns, but not withasync
-await
. – Cushiony