Last active
February 14, 2022 19:49
-
-
Save ts95/300c5a815393087c72cc to your computer and use it in GitHub Desktop.
OS X detect new screenshot event with Swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
typealias NewFileCallback = (fileURL: NSURL) -> Void | |
class ScreenshotDetector: NSObject, NSMetadataQueryDelegate { | |
let query = NSMetadataQuery() | |
var newFileCallback: NewFileCallback? | |
override init() { | |
super.init() | |
let center = NSNotificationCenter.defaultCenter() | |
center.addObserver(self, selector: Selector("queryUpdated:"), name: NSMetadataQueryDidStartGatheringNotification, object: query) | |
center.addObserver(self, selector: Selector("queryUpdated:"), name: NSMetadataQueryDidUpdateNotification, object: query) | |
center.addObserver(self, selector: Selector("queryUpdated:"), name: NSMetadataQueryDidFinishGatheringNotification, object: query) | |
query.delegate = self | |
query.predicate = NSPredicate(format: "kMDItemIsScreenCapture = 1") | |
query.startQuery() | |
} | |
deinit { | |
query.stopQuery() | |
} | |
func queryUpdated(notification: NSNotification) { | |
if let userInfo = notification.userInfo { | |
for v in userInfo.values { | |
let items = v as! [NSMetadataItem] | |
if items.count > 0 { | |
let item = items[0] | |
if let filename = item.valueForAttribute("kMDItemFSName") as? String { | |
let filenameWithPath = NSString(string: "~/Desktop/" + filename).stringByExpandingTildeInPath | |
let url = NSURL(fileURLWithPath: filenameWithPath, isDirectory: false) | |
if let cb = self.newFileCallback { | |
cb(fileURL: url) | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
//////////////////////////// | |
// Usage // | |
//////////////////////////// | |
// Because this object is observing events it should stay | |
// in memory for the duration of its usage. | |
// In a view controller for instance it should be allocated | |
// in the class scope. If its reference is stored inside | |
// a method it will be deallocated automatically when the | |
// method returns and consequently stop obsering any events. | |
let detector = ScreenshotDetector() | |
// The actual callback can be assigned anywhere there's | |
// a reference to the instance. | |
detector.newFileCallback = { fileURL in | |
// fileURL is an NSURL instance of the screenshot file. | |
} |
Does this require sandbox permissions? I'm not receiving any notifications.
I'm pretty sure this approach to subscribing to screenshot updates doesn't work anymore. It broke a couple of years ago and I haven't looked further into it since.
Yeah looks like if I remove sandboxing it works. Which is fine for my demo app. There might be an entitlement I can set but for now that's fine. 👍
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
I tried to call this class, but I made a mistake.
2020-02-09 19:00:51.389151+0100 XXX [59278:4184587] -[XXX.ScreenshotDetector queryUpdated:]: unrecognized selector sent to instance 0x600000221400
2020-02-09 19:00:51.389514+0100 XXX[59278:4184587] Failed to set (contentViewController) user defined inspected property on (NSWindow): -[XXX.ScreenshotDetector queryUpdated:]: unrecognized selector sent to instance 0x600000221400
2020-02-09 19:00:51.876467+0100 XXX[59278:4184587] -[XXX.ScreenshotDetector queryUpdated:]: unrecognized selector sent to instance 0x600000221400
2020-02-09 19:00:51.912782+0100 XXX[59278:4184587] [General] -[XXX.ScreenshotDetector queryUpdated:]: unrecognized selector sent to instance 0x600000221400
please help me