0
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Swift:2つのNSTableView間でアイテムをドラッグ&ドロップ

Last updated at Posted at 2020-06-18

Demo

table.gif

下準備

対象となる2つのTableViewのそれぞれにおいて、TableColumnTableCellViewのIdentifierに同じキーワードを指定しておく。(テーブルのアイテムを追加するための措置)

group.png

ソース

import Cocoa

class ViewController: NSViewController {

    @IBOutlet weak var tableViewA: NSTableView!
    @IBOutlet weak var tableViewB: NSTableView!

    let registeredType = NSPasteboard.PasteboardType.string
    var groupA: [String] = ["Apple", "Banana", "Grape", "Peach"]
    var groupB: [String] = ["Gomi", "Hoge", "Piyo"]

    override func viewDidLoad() {
        super.viewDidLoad()

        tableViewA.delegate = self
        tableViewB.delegate = self
        tableViewA.dataSource = self
        tableViewB.dataSource = self

        // ドラッグ & ドロップのために必要
        tableViewA.registerForDraggedTypes([registeredType])
        tableViewB.registerForDraggedTypes([registeredType])

        tableViewA.reloadData()
        tableViewB.reloadData()
    }

}

extension ViewController: NSTableViewDelegate, NSTableViewDataSource {

    func numberOfRows(in tableView: NSTableView) -> Int {
        // それぞれのテーブルのアイテム数を返す
        if tableView === tableViewA {
            return groupA.count
        } else if tableView === tableViewB {
            return groupB.count
        }
        return 0
    }

    func tableView(_ tableView: NSTableView,
                   viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        let cell = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView
        if tableView === tableViewA {
            cell?.textField?.stringValue = groupA[row]
        } else if tableView === tableViewB {
            cell?.textField?.stringValue = groupB[row]
        }
        return cell
    }

    // drag & drop
    func tableView(_ tableView: NSTableView,
                   validateDrop info: NSDraggingInfo,
                   proposedRow row: Int,
                   proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {
        if dropOperation == .above {
            return NSDragOperation.move
        }
        return .every
    }

    func tableView(_ tableView: NSTableView,
                   writeRowsWith rowIndexes: IndexSet,
                   to pboard: NSPasteboard) -> Bool {
        guard tableView === tableViewA || tableView === tableViewB else {
            return false
        }
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: rowIndexes,
                                                        requiringSecureCoding: false)
            pboard.declareTypes([registeredType], owner: self)
            pboard.setData(data, forType: registeredType)
            return true
        } catch {
            Swift.print(error.localizedDescription)
        }
        return false
    }

    func tableView(_ tableView: NSTableView,
                   acceptDrop info: NSDraggingInfo,
                   row: Int,
                   dropOperation: NSTableView.DropOperation) -> Bool {
        let pboard = info.draggingPasteboard
        guard
            let data = pboard.data(forType: registeredType),
            let rowIndexes = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? IndexSet,
            let source = info.draggingSource as? NSTableView,
            let sourceRow = rowIndexes.min()
            else { return false }
        let targetIndexes = rowIndexes.sorted()
        var tmp = [String]()
        let beforeCount = targetIndexes.filter({ (n) -> Bool in
            return n < row
        }).count
        if source == tableViewA && tableView == tableViewB {
            let value = groupA[sourceRow]
            groupA.remove(at: sourceRow)
            groupB.append(value)
        }
        if source == tableViewB && tableView == tableViewA {
            let value = groupB[sourceRow]
            groupB.remove(at: sourceRow)
            groupA.append(value)
        }
        tableViewA.reloadData()
        tableViewB.reloadData()
        return true
    }

}

kyome

0
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?