How to add listener for all running applications

2.4k Views Asked by At

I want to display a list of all running application names.

Issue: It doesn't add an app that is running after the function is called. Therefore, it doesn't add the app name to the list simultaneously.

Goal: I want to add a listener, so if a new app is running it will add it to the array simultaneously without restarting the app or recalling the function again.

func allRunningApplications() {

        for runningApplication in NSWorkspace.shared.runningApplications {

            let appName = runningApplication.localizedName

            // Add App Name to Array
            array.append(appName)
    }
}
3

There are 3 best solutions below

2
James Bucanek On BEST ANSWER

I mentioned the "did launch", et. al., notifications because you didn't explain why you wanted to monitor the set of running applications.

If you are only interested in whether a specific app has launched (or quit), it would probably be easier to use the NSWorkspace notifications:

(untested code)

let center = NSWorkspace.shared.notificationCenter
center.addObserver(forName: NSWorkspace.didLaunchApplicationNotification,
                    object: nil, // always NSWorkspace
                     queue: OperationQueue.main) { (notification: Notification) in
                        if let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication {
                            if app.bundleIdentifier == "com.apple.Terminal" {
                                // User just launched the Terminal app; should we be worried?
                            }
                        }
}

Note that workspace notifications are posted to NSWorkspace's private notification center, not the default notification center, so remember to add your observers there.

5
Business Tomcat On

You could poll the runningApplications property (check it every x seconds) to test, if there is a new application. But it's not recommended: https://developer.apple.com/documentation/appkit/nsworkspace/1534059-runningapplications

Similar to the NSRunningApplication class’s properties, this property will only change when the main run loop is run in a common mode. Instead of polling, use key-value observing to be notified of changes to this array property.

So use key-value observing on NSWorkspace.shared.runningApplications

A good example can be found here: https://www.ralfebert.de/ios-examples/swift/property-key-value-observer/

For your code it should be something like this:

var observers = [NSKeyValueObservation]()

override func viewDidLoad() {
    super.viewDidLoad()

    observeModel()
}

func observeModel() {
    self.observers = [
        NSWorkspace.shared.observe(\.NSWorkspace.runningApplications, options: [.initial]) {(model, change) in
            // runningApplications changed, so update your UI or something else
        }
    ]
}

(untested code)

0
Bharath Suresh On

You can try using the notification centre of NSWorkspace.

    self.workspace = [NSWorkspace new];
    NSArray *myObserver;
    myObserver = (NSArray*) [[[NSWorkspace sharedWorkspace] notificationCenter] addObserverForName:  NSWorkspaceWillLaunchApplicationNotification object:nil queue:nil usingBlock:^(NSNotification *note)
                         {
                             if(note)
                             {
                               //do your action
                             }
                         }
                        ];

NSWorkspaceWillLaunchApplicationNotification will notify you if any application is about to be launched.