16

I'm a beginner with Swift, and I'm trying to figure out how can I read what has been copied to the clipboard On macOS (Swift 3)? I've searched a lot but can't seem to find anything that works.

A few of the things I've tried from online:

var pasteboardItems: [NSPasteboardItem]? { get }
print("\(pasteboardItems)")

and

let pb = NSPasteboard.general()
pb.string(forType: NSPasteboardTypeString)

print("\(pb)")

and

let pasteboard = UIPasteboard.general
if let string = pasteboard.string {
    // text was found and placed in the "string" constant
}

and lastly

func paste(sender: AnyObject?) {

    let pasteboard = NSPasteboard.generalPasteboard()

    if let nofElements = pasteboard.pasteboardItems?.count {

        if nofElements > 0 {


            // Assume they are strings

            var strArr: Array<String> = []
            for element in pasteboard.pasteboardItems! {
                if let str = element.stringForType("public.utf8-plain-text") {
                    strArr.append(str)
                }
            }


            // Exit if no string was read

            if strArr.count == 0 { return }


            // Perform the paste operation

            dataSource.cmdPaste(strArr)
       }
    }        
}
ronatory
  • 7,156
  • 4
  • 29
  • 49
John
  • 371
  • 1
  • 3
  • 11
  • 1
    Your 2nd code is the only attempt in the right direction. The 3rd is for iOS. The 4th is Swift 2. The 1st makes no sense. – rmaddy Jan 03 '17 at 22:00

5 Answers5

28

Works for Swift 3 and Swift 4

// Set string to clipboard
let pasteboard = NSPasteboard.general
pasteboard.declareTypes([NSPasteboard.PasteboardType.string], owner: nil)
pasteboard.setString("Good Morning", forType: NSPasteboard.PasteboardType.string)

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

// Access the item in the clipboard
let firstClipboardItem = clipboardItems[0] // Good Morning
Santa Claus
  • 984
  • 1
  • 12
  • 26
ronatory
  • 7,156
  • 4
  • 29
  • 49
6

Another Swift 4 Solution

// Write to pasteboard
let pasteboard = NSPasteboard.general
pasteboard.declareTypes([NSPasteboard.PasteboardType.string], owner: nil)
pasteboard.setString("Good Morning", forType: NSPasteboard.PasteboardType.string)

// Read from pasteboard
let read = pasteboard.pasteboardItems?.first?.string(forType: .string)
Koray Birand
  • 1,956
  • 17
  • 22
5

Times have changed. In Swift 3+ you would do it like this: (if you are only interested in strings)

func clipboardContent() -> String?
{
    return NSPasteboard.general.pasteboardItems?.first?.string(forType: .string)
}
LimeRed
  • 1,278
  • 13
  • 18
  • 3
    At least in Swift 5, no need for `.pasteboardItems?.first?`, this works: `NSPasteboard.general.string(forType: .string)`. – user137369 Feb 18 '22 at 16:53
2

Another solution.

class ViewController : NSViewController {

  @IBAction func pasteMenuItemAction(_ sender: NSMenuItem) {
    let p = NSPasteboard.general
    let x = p.readObjects(forClasses: [NSString.self], options: nil)
    let s = x as! [NSString]
    if 0 < s.count {
      print(s[0])
    }
  }

}

That func pasteMenuItemAction() is bound to an Edit > Paste menu item.

I use writeObjects() for Edit > Copy. So it is natural for me to use its counterpart readObjects() here.

Confirmed with Xcode 9.2, Swift 4

Added:

One of the solutions for Edit > Copy:

  @IBAction func copyMenuItemAction(_ sender: NSMenuItem) {
    let t = "Hello!"
    let p = NSPasteboard.general
    p.clearContents()
    p.writeObjects([t as NSPasteboardWriting])
  }

That func copyMenuItemAction() is bound to an Edit > Copy menu item.

Tora
  • 970
  • 1
  • 8
  • 15
-1

Easier ✅ Swift 4:

@IBAction func pasteAction(_ sender: Any) {
    guard let stringToPaste: String = UIPasteboard.general.items.last?.first?.value as? String else { return }
    MYTEXTVIEW.text = stringToPaste
}
Joshua Hart
  • 772
  • 1
  • 21
  • 31