1

I'm attempting to learn Swift in my spare time and have embarked on a mini-project to try and learn with purpose. I'm trying to create a MacOS app that shows the first 10 characters of the clipboard on the menu bar.

I've had some success, I've managed to get the app to show the clipboard content, however it works only once; if the clipboard content changes it doesn't update.

I've discovered that using ChangeCount I can keep track of the clipboard, however I'm now stuck on how to structure the code to make the menu bar update.

Here's the (relevant) code so far:

timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { (t) in
    if self.lastChangeCount != self.pasteboard.changeCount {

    }
}

var clipboardItems: [String] = []
for element in pasteboard.pasteboardItems! {
    if let str = element.string(forType: NSPasteboard.PasteboardType(rawValue: "public.utf8-plain-text")) {
        clipboardItems.append(str)
    }
}

let ClipboardItem = String(clipboardItems[0].prefix(10)) // Gets 10 chars of first item

let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(
    withLength: NSStatusItem.variableLength)
statusBarItem.button?.title = ClipboardItem

Any help would be much appreciated.

morgyface
  • 368
  • 1
  • 9

1 Answers1

2

You're nearly there - just put the pasteboard extraction code inside your timer closure. Be careful about force unwrapping things, though. pasteboard.pasteboardItems might be nil and clipboardItems might be empty. You could try something like this:

if self.lastChangeCount != self.pasteboard.changeCount {
    var clipboardItems: [String] = []

    if let items = self.pasteboard.pasteboardItems {
        for element in items {
            if let str = element.string(forType: NSPasteboard.PasteboardType(rawValue: "public.utf8-plain-text")) {
                clipboardItems.append(str)
            }
        }
    }

    let clip = clipboardItems.first?.prefix(10) ?? "Clips"
    self.statusBarItem.button?.title = String(clip)

    self.lastChangeCount = self.pasteboard.changeCount
}
Loengard
  • 401
  • 2
  • 7
  • Thank you very much @Loengard, however I'm getting the following error: "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" For line `let clip = clipboardItems.first?.prefix(10) ?? "Clips"` I strongly suspect his is my error not yours. – morgyface May 09 '20 at 18:57
  • Strange, since you're not implicitly unwrapping anything. It works fine for me. Maybe try Product > Clean Build Folder and run again. Sometimes cruft can be left over from previous runs. – Loengard May 10 '20 at 00:54