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
        }
    }
}


Posted in Cocoa, Swift Tagged with: , , ,
One comment 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/

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

Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Recent Posts


Hit Counter provided by technology news