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?
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?
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.
In Swift 3 and later, the equivalent code is:
RunLoop.main.run()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With