Skip to content

Instantly share code, notes, and snippets.

Last active October 6, 2023 14:15
Show Gist options
  • Star 20 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save Daemon-Devarshi/13efd24f027a775ee862 to your computer and use it in GitHub Desktop.
Save Daemon-Devarshi/13efd24f027a775ee862 to your computer and use it in GitHub Desktop.
A class which performs polling to determine the newly copied url of desired kind in an external app
// PasteboardWatcher.swift
// PasteboardWatcher
// Created by Devarshi Kulshreshtha on 6/19/15.PasteboardWatcher
// Copyright © 2015 Devarshi Kulshreshtha. All rights reserved.
import Cocoa
/// Protocol defining the methods which delegate has/ can implement
protocol PasteboardWatcherDelegate {
/// the method which is invoked on delegate when a new url of desired kind is copied
/// - Parameter copiedUrl: the newly copied url of desired kind
func newlyCopiedUrlObtained(copiedUrl copiedUrl : NSURL)
/// Use this class to notify a delegate once a url with specified kind is copied
/// - Credit goes to: **Josh Goebel**
/// - His wonderful pastie: [PasteboardWatcher in objective-c](
class PasteboardWatcher : NSObject {
// assigning a pasteboard object
private let pasteboard = NSPasteboard.generalPasteboard()
// to keep track of count of objects currently copied
// also helps in determining if a new object is copied
private var changeCount : Int
// used to perform polling to identify if url with desired kind is copied
private var timer: NSTimer?
// the delegate which will be notified when desired link is copied
var delegate: PasteboardWatcherDelegate?
// the kinds of files for which if url is copied the delegate is notified
private let fileKinds : [String]
/// initializer which should be used to initialize object of this class
/// - Parameter fileKinds: an array containing the desired file kinds
init(fileKinds: [String]) {
// assigning current pasteboard changeCount so that it can be compared later to identify changes
changeCount = pasteboard.changeCount
// assigning passed desired file kinds to respective instance variable
self.fileKinds = fileKinds
/// starts polling to identify if url with desired kind is copied
/// - Note: uses an NSTimer for polling
func startPolling () {
// setup and start of timer
timer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: Selector("checkForChangesInPasteboard"), userInfo: nil, repeats: true)
/// method invoked continuously by timer
/// - Note: To keep this method as private I referred this answer at stackoverflow - [Swift - NSTimer does not invoke a private func as selector](
@objc private func checkForChangesInPasteboard() {
// check if there is any new item copied
// also check if kind of copied item is string
if let copiedString = pasteboard.stringForType(NSPasteboardTypeString) where pasteboard.changeCount != changeCount {
// obtain url from copied link if its path extension is one of the desired extensions
if let fileUrl = NSURL(string: copiedString) where self.fileKinds.contains(fileUrl.pathExtension!){
// invoke appropriate method on delegate
self.delegate?.newlyCopiedUrlObtained(copiedUrl: fileUrl)
// assign new change count to instance variable for later comparison
changeCount = pasteboard.changeCount
Copy link

how this work?? Please explain

@Gk19011994 I believe that comments added to the code explains all. In summary it performs data polling to check the changeCount on pasteboard object.

Copy link

mizlan commented Apr 16, 2021

Can this be generalized to more than just URLs? It seems to work only on single-line copies right now.

Copy link

mizlan commented Apr 16, 2021

I guess I can just avoid coercing it into an NSURL

Copy link

Daemon-Devarshi commented Apr 25, 2021 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment