title: Reorder and Move NSTableView Row with NSPasteboard
body: <p>I have an <code>NSTableView</code> where I can drag and drop table rows to reorder them. This works by setting a drag type in my view controller:</p>
  <pre><code>@IBOutlet weak var tableView: NSTableView!
  let dragType = NSPasteboard.PasteboardType(rawValue: &quot;myapp.task&quot;)
  
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.registerForDraggedTypes([dragType])
  }
  </code></pre>
  <p>...and then implementing the reordering with these table delegate methods:</p>
  <pre><code>//Start drag
  func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -&gt; NSPasteboardWriting? {
    let item = NSPasteboardItem()
    item.setString(String(row), forType: dragType)
    return item
  }
  
  //Verify proposed drop
  func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -&gt; NSDragOperation {
    if dropOperation == .above {
      return .move
    }else{
      return []
    }
  }
  
  //Accept drop of one or multiple rows
  func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -&gt; Bool {
    var oldIndexes = [Int]()
    info.enumerateDraggingItems(options: [], for: tableView, classes: [NSPasteboardItem.self], searchOptions: [:]) { dragItem, _, _ in
      if let str = (dragItem.item as! NSPasteboardItem).string(forType: self.dragType), let index = Int(str) {
        oldIndexes.append(index)
      }
    }
  
    //Do a bunch of logic to reorder the table rows...
  }
  </code></pre>
  <p>Now, in addition to reordering my table rows, I want to be able to drag a row and drop it somewhere else in my app--sort of like moving the row to a different place.</p>
  <p>I have a custom <code>NSView</code> set up as the drag destination for this, and I can drag a table row and the custom view reacts appropriately with a table row dragged over it:</p>
  <pre><code>class MyCustomView: NSView{
  
    required init?(coder: NSCoder) {
      super.init(coder: coder)
      let taskDragType = NSPasteboard.PasteboardType(rawValue: &quot;myapp.task&quot;)
      registerForDraggedTypes([taskDragType])
    }
  
    override func draggingEntered(_ sender: NSDraggingInfo) -&gt; NSDragOperation {
      //...
    }
    override func draggingExited(_ sender: NSDraggingInfo?) {
      //...
    }
  }
  </code></pre>
  <p>But the part I'm unclear on is how to get the table row, and its associated object set as a property on the <code>NSTableCellView</code>, when the drop occurs:</p>
  <pre><code>//This is another method in MyCustomView
  
  override func performDragOperation(_ draggingInfo: NSDraggingInfo) -&gt; Bool {
  
    guard let items = draggingInfo.draggingPasteboard.pasteboardItems else{ return false }
  
    for item in items{
      print(&quot;---&quot;)
      print(item) //&lt;-- NSPasteboardItem
      let index = item.propertyList(forType: NSPasteboard.PasteboardType(rawValue: &quot;myapp.task&quot;))
      print(index) //&lt;-- Index of the table row
      //How can I also get the task object associated with the row?
    }
  }
  </code></pre>
  <p>I can get the index of the row, but what I need is the entire object from the row's data source so I can take action on the object it represents. My suspicion is that I need to change how I'm using <code>pasteboardWriterForRow</code> to put my object on the pasteboard, but I'm unsure how to do that.</p>
  <p>How can I pass both the row index <em>and</em> the object to the pasteboard?</p>