Swift NSTableView Drag & Drop

Swift – NSTableView Drag & Drop

In this Post we will create a demo application to demonstrate NSTableView Drag and Drop.

The drag and drop is allowed between a Source Table View and a Target Table View and vice versa.

Drag and drop is also allowed inside the target table view to reorder the data.

  • Open Xcode and Create a new cocoa project.
  • Choose Swift as the programming language
  • In the MainMenu.xib add two cell based table views.
  • Make the AppDelegate as the datasource and delegate for both the tables.
  • Add the below code in AppDelegate.swift

The source code can be downloaded from https://github.com/knowstack/DDCocoaSampleCode/tree/master/TableViewDragDrop

NSTableView_DragDrop


//
//  AppDelegate.swift
//  TableViewDragDrop
//
//  Created by Debasis Das on 12/12/14.
//  Copyright (c) 2014 Knowstack. All rights reserved.
//

import Cocoa

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate,NSTableViewDelegate,NSTableViewDataSource {

    @IBOutlet weak var window: NSWindow!
    @IBOutlet weak var sourceTableView: NSTableView!
    @IBOutlet weak var targetTableView: NSTableView!
    
    var sourceDataArray:[String] = ["Debasis Das","John Doe","Jane Doe","Mary Jane"]
    var targetDataArray:[String] = []
    //Here we are declaring two data array that will be the datasource for the two table views.
    //Initially the source data array is initialized with some demo data


    func applicationDidFinishLaunching(aNotification: NSNotification) {
        //Here we are registering the two tables for the dragged types. In case you are using a NSWindowController or a NSViewController as the delegate of your table view, you can put the below code in the awakeFromNib or viewDidLoad methods respectively
        var registeredTypes:[String] = [NSStringPboardType]
        sourceTableView.registerForDraggedTypes(registeredTypes)
        targetTableView.registerForDraggedTypes(registeredTypes)
    }

    func numberOfRowsInTableView(aTableView: NSTableView!) -> Int
    {
        var numberOfRows:Int = 0;
        if (aTableView == sourceTableView)
        {
            numberOfRows = sourceDataArray.count
        }
        else if (aTableView == targetTableView)
        {
            numberOfRows = targetDataArray.count
        }
        return numberOfRows
    }

    func tableView(tableView: NSTableView!, objectValueForTableColumn tableColumn: NSTableColumn!, row: Int) -> AnyObject!
    {
        var newString:String = ""
        if (tableView == sourceTableView)
        {
            newString = sourceDataArray[row]
        }
        else if (tableView == targetTableView)
        {
            newString = targetDataArray[row]
        }
        return newString;
    }

    func tableView(aTableView: NSTableView,
        writeRowsWithIndexes rowIndexes: NSIndexSet,
        toPasteboard pboard: NSPasteboard) -> Bool
    {
        if ((aTableView == sourceTableView) || (aTableView == targetTableView))
        {
            var data:NSData = NSKeyedArchiver.archivedDataWithRootObject(rowIndexes)
            var registeredTypes:[String] = [NSStringPboardType]
            pboard.declareTypes(registeredTypes, owner: self)
            pboard.setData(data, forType: NSStringPboardType)
            return true
            
        }
        else
        {
            return false
        }
    }

    func tableView(aTableView: NSTableView,
        validateDrop info: NSDraggingInfo,
        proposedRow row: Int,
        proposedDropOperation operation: NSTableViewDropOperation) -> NSDragOperation
    {
        if operation == .Above 
        {
            return .Move
        }
        return .All
        
    }
    
    func tableView(tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableViewDropOperation) -> Bool
    {
        var data:NSData = info.draggingPasteboard().dataForType(NSStringPboardType)!
        var rowIndexes:NSIndexSet = NSKeyedUnarchiver.unarchiveObjectWithData(data) as NSIndexSet
        
        if ((info.draggingSource() as NSTableView == targetTableView) && (tableView == targetTableView))
        {
            var value:String = targetDataArray[rowIndexes.firstIndex]
            targetDataArray.removeAtIndex(rowIndexes.firstIndex)
            if (row > targetDataArray.count)
            {
                targetDataArray.insert(value, atIndex: row-1)
            }
            else
            {
                targetDataArray.insert(value, atIndex: row)
            }
            targetTableView.reloadData()
            return true
        }
        else if ((info.draggingSource() as NSTableView == sourceTableView) && (tableView == targetTableView))
        {
            var value:String = sourceDataArray[rowIndexes.firstIndex]
            sourceDataArray.removeAtIndex(rowIndexes.firstIndex)
            targetDataArray.append(value)
            sourceTableView.reloadData()
            targetTableView.reloadData()
            return true
        }
        else
        {
            return false
        }
    }
}

Another sample where the drag and drop happens between TableViews owned by different view controllers in a vertical split view
TableView-DragDrop across view controllers
shtags=”swift,NSTableView,DragDrop”>Tweet

Posted in Cocoa, Swift Tagged with: , , ,
14 comments on “Swift NSTableView Drag & Drop
  1. Debasis Das says:

    For the objective C Implementation please have a look at the below link

    http://www.knowstack.com/nstableview-dragdrop/

  2. Rien says:

    Thanks!

    However it would be better to replace NSStringPboardType with “com.yoursite.yourproject.yourtype”. That way the copy & paste is only possible between the two tables in the example.

  3. Perres says:

    Hi and thank you very much for this great tutorial.
    one question.

    is it possible to realize this situation in a split view?
    i mean:

    split view
    -> item 1 (View Controller): source tableview
    -> item 2 (View Controller): target tableview

    and both item as a separate class file.
    is it possible? if yes – can you show me how?

    thanks a lot !

  4. Perres says:

    thanks but the new download link doesn’t work

  5. Edward says:

    Man, I can’t thank you for this. I’ve been looking for this type of drag and drop implementation. This really helps me. Just wow.

1 Pings/Trackbacks for "Swift NSTableView Drag & Drop"

Leave a Reply

Your email address will not be published. Required fields are marked *

*