title: NSPasteboard Copy Dragged and Dropped File
body: <p>Although I have working code, I'm confused about whether I'm taking the right approach to <code>NSPasteboard</code> and I am reaching out to see if anyone can help me clarify the best approach.</p>
  
  <p>There doesn't appear to be any full documentation written by Apple about dragging and dropping since 2012 and in that time there seems to have been deprecation and a change in the way (especially with sandboxed apps) in which you are supposed to implement it. After much messing around I discovered that the file URL supplied by the dragged pasteboard reveals its true path (as opposed to the anonymised string of numbers which make up the url) when you access its path property and this enables a regular copy to be made using <code>FileManager</code>. </p>
  
  <p>My question is, am I following the right procedure here? Casting the <code>NSURL</code> obtained from the pasteboard to a <code>URL</code> type and using it in <code>copyItem(at:URL, to:URL)</code> doesn't work (even though copying and pasting the same url into Safari enables me to view the file). Hence I use instead <code>copyItem(atPath:String, toPath:String)</code>. To further labour this point, is there a method for the <code>URL</code> type that replaces <code>NSURL(from:NSPasteboard)</code>? It seems like there should be.</p>
  
  <p>Anyway here's the code I have working (please ignore the code inside draggingEntered: for now, it just gets things working for testing, and the fact that I register for <code>NSFilenamesPboardType</code> but then ignore it can also be overlooked also).</p>
  
  <pre><code>import Cocoa
  
  class DraggerView: NSView {
      let types = [NSURLPboardType, NSFilenamesPboardType]
      var directory:URL!
  
      override init(frame: NSRect) {
          super.init(frame: frame)
          register(forDraggedTypes: types)
          if  let dir = URL(string:NSTemporaryDirectory())
          {
              directory = dir
          }
      }
  
  
      required init?(coder: NSCoder) {
          super.init(coder: coder)
          register(forDraggedTypes: types)
          if  let dir = URL(string:NSTemporaryDirectory())
          {
              directory = dir
          }
      }
  
      override func draw(_ dirtyRect: NSRect)  {
          super.draw(dirtyRect)
          NSColor.white.set()
          NSRectFill(dirtyRect)
      }
  
      override func draggingEntered(_ sender: NSDraggingInfo) -&gt; NSDragOperation  {
          return NSDragOperation.copy
      }
  
  
      override func performDragOperation(_ sender: NSDraggingInfo) -&gt; Bool {
  
          let pboard = sender.draggingPasteboard()
          if let types = pboard.types, types.contains(NSURLPboardType) {
  
  
              // add file name to save to loaction
              if let fileURL = NSURL(from:pboard), let filename = fileURL.lastPathComponent {
                  directory.appendPathComponent(filename)
                  do {
                      try FileManager.default.copyItem(atPath:fileURL.path!, toPath:directory.path)
                  }
                  catch {
                      // something went wrong
                  }
              }
  
  
              return true
          }
          else { return false }
      }
  }
  </code></pre>
  
  <p>One final point is that the docs keep referring to using UTIs when registering for dragged types, but I'm not clear how far this extends. Should I replace <code>NSURLPboardType</code> and <code>NSFilenamesPboardType</code> with UTIs?</p>