CFRunLoop in Swift Command Line Program

拈花ヽ惹草 提交于 2019-11-26 03:59:44

问题


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?


回答1:


It seems like Martin R's answer should work, however I was able to get the socket to stay open with a single function call. At the end of the startServer() function, I put the line:

CFRunLoopRun()

Which worked.




回答2:


The NSRunLoop Class Reference has an example for a simple runloop:

BOOL shouldKeepRunning = YES;        // global

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

which can be translated to Swift:

var shouldKeepRunning = true        // global

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

Alternatively, it might be sufficient to just call

dispatch_main()

Update for Swift 3.1:

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

or

dispatchMain()


来源:https://stackoverflow.com/questions/25126471/cfrunloop-in-swift-command-line-program

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!