CFRunLoop en el progtwig Swift Command Line

Estoy escribiendo una aplicación de línea de comandos en Swift utilizando un marco de terceros que (si entiendo el código correctamente) depende de las devoluciones de llamada GCD para completar ciertas acciones cuando un socket recibe datos. Para entender mejor el marco, he estado jugando con una aplicación Cocoa de muestra que el autor del framework escribió para acompañar el framework.

Como la aplicación de muestra es una aplicación Cocoa, los bucles de ejecución se manejan automáticamente. Incluyo fragmentos de código de la aplicación de muestra (licencia de MIT) para dar una idea de cómo funciona:

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() ... } } 

Me gustaría modificar la aplicación de muestra para ejecutar desde la línea de comando. Cuando coloco la función startServer () en una aplicación de línea de comandos, se ejecuta, pero el socket se cierra inmediatamente después de que se abre, y el progtwig termina de ejecutarse con un código de salida 0. Este es el comportamiento esperado, ya que no hay bucles de ejecución en un proyecto de línea de comando de Xcode, y por lo tanto el progtwig no sabe esperar a que el socket reciba datos.

Creo que la forma correcta de mantener el socket abierto y que el progtwig funcione continuamente sería poner el hilo principal en un CFRunLoop. Revisé la documentación de Apple y, a excepción de la referencia básica de API, no hay nada en subprocesos en Swift. Miré recursos de terceros, pero todos incluyen hilos alternativos en las aplicaciones iOS y Cocoa. ¿Cómo implemento correctamente un CFRunLoop para el hilo principal?

Parece que la respuesta de Martin R debería funcionar; sin embargo, pude lograr que el socket se mantuviera abierto con una única llamada a función. Al final de la función startServer (), coloco la línea:

 CFRunLoopRun() 

Lo cual funcionó.

La referencia de clase NSRunLoop tiene un ejemplo para un runloop simple:

 BOOL shouldKeepRunning = YES; // global NSRunLoop *theRL = [NSRunLoop currentRunLoop]; while (shouldKeepRunning && [theRL runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]); 

que se puede traducir a Swift:

 var shouldKeepRunning = true // global let theRL = NSRunLoop.currentRunLoop() while shouldKeepRunning && theRL.runMode(NSDefaultRunLoopMode, beforeDate: NSDate.distantFuture()) { } 

Alternativamente, podría ser suficiente simplemente llamar

 dispatch_main() 

Actualización para Swift 3.1:

 let theRL = RunLoop.current while shouldKeepRunning && theRL.run(mode: .defaultRunLoopMode, before: .distantFuture) { } 

o

 dispatchMain()