I’m building a MacOS application using react native. I want to find out when the user switches applications and grab screenshots when they occur. I have the following toy implementation:
import Foundation
import AppKit
@objc(ScreenShotModule)
public class ScreenShotModule: NSObject, RCTBridgeModule {
public static func moduleName() -> String! {
return "ScreenShotModule"
}
var count:Int = 0
override init() {
super.init()
print("called init")
NotificationCenter.default.addObserver(
self,
selector: #selector(appDidBecomeActive),
name: NSWorkspace.didActivateApplicationNotification,
object: nil)
}
@objc func appDidBecomeActive(notification: NSNotification) {
print("got notified")
let displayId = CGMainDisplayID()
guard let image = CGDisplayCreateImage(displayId) else { return }
let bitmapRep = NSBitmapImageRep(cgImage: image)
guard let imageData = bitmapRep.representation(using: .png, properties: [:]) else { return }
let fileManager = FileManager.default
let directoryURLs = fileManager.urls(for: .picturesDirectory, in: .userDomainMask)
if let documentDirectory = directoryURLs.first {
let filePath = documentDirectory.appendingPathComponent("screenshot_\(count).png")
do {
try imageData.write(to: filePath)
count += 1
print("Screenshot saved to: \(filePath)")
} catch {
print("Error saving screenshot: \(error)")
}
}
}
@objc func triggerAppDidBecomeActive() {
let dummyNotification = NSNotification(name: NSNotification.Name(""), object: nil)
self.appDidBecomeActive(notification: dummyNotification)
}
@objc func postNotification() {
print("posted!")
NotificationCenter.default.post(name: NSWorkspace.didActivateApplicationNotification, object: "foo",
userInfo: ["key": "Value"])
}
@objc public static func requiresMainQueueSetup() -> Bool {
return true
}
}
This works in that I can manually take screenshots via triggerAppDidBecomeActive, and I can take screenshots upon posting fake events via postNotification. However, while I’m running the app and switching between applications, no screenshots are taken. So somehow, my switching applications does not send events to, or otherwise does not trigger:
NotificationCenter.default.addObserver(
self,
selector: #selector(appDidBecomeActive),
name: NSWorkspace.didActivateApplicationNotification,
object: nil)
I’ve turned on and off Application sandboxing without change. I’ve also tried using DistributedNotificationCenter and that doesn’t work either. How can I figure out when a user switches active applications?
>Solution :
You’re using NotificationCenter.default.addObserver, but you should be using NSWorkspace.shared.addObserver
I believe this is universally true for the NSWorkspace.* notifications.