问题
What I am trying to do
I want to run a daemon process that can listen to OSX system events like NSWorkspaceWillLaunchApplicationNotification
in an command line tool
xcode project? Is that possible? And if not, why not and are there any work arounds or hacks?
Some code samples
The following sample code from a swift 2
cocoa application
project sets up a system event listener, which calls WillLaunchApp
every time an OSX app gets started. (this works just fine)
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(aNotification: NSNotification) {
NSWorkspace.sharedWorkspace()
.notificationCenter.addObserver(self,
selector: "WillLaunchApp:",
name: NSWorkspaceWillLaunchApplicationNotification, object: nil)
}
func WillLaunchApp(notification: NSNotification!) {
print(notification)
}
}
In contrast this simingly similar swift 2
command line tool
project will not call WillLaunchApp
.
import Cocoa
class MyObserver: NSObject
{
override init() {
super.init()
NSWorkspace.sharedWorkspace()
.notificationCenter.addObserver(self,
selector: "WillLaunchApp:",
name: NSWorkspaceWillLaunchApplicationNotification, object: nil)
}
func WillLaunchApp(notification: NSNotification!) {
// is never called
print(notification)
}
}
let observer = MyObserver()
while true {
// simply to keep the command line tool alive - as a daemon process
sleep(1)
}
I am guessing I am missing some cocoa
and/or xcode
fundamentals here, but I cannot figure out which ones. Maybe it is related to the while-true loop, which might be blocking the events. If so, is there a correct way to run a daemon process?
回答1:
It turns out using while true
loop does block the main-thread.
Simply replace the while true
loop with NSRunLoop.mainRunLoop().run()
and you have a daemon process.
I read the sources of swifter (a swift-based server), which is doing the same.
回答2:
In Swift 3 and later, the equivalent code is:
RunLoop.main.run()
来源:https://stackoverflow.com/questions/31469532/how-to-create-a-minimal-daemon-process-in-a-swift-2-command-line-tool