NSTableview - 拖放分为两个类和控制器

时间:2017-05-31 11:22:18

标签: macos cocoa swift3

我找到了这个有用的教程,用于实现使用nstabelview拖放: https://drive.google.com/open?id=0B8PBtMQt9GdONzV3emZGQWUtdmM

这很好。

但我想将两个表视图拆分为不同的视图控制器和具有拆分视图的类:

一个拆分视图控制器:

  • 第1项:带有源nstableview的视图控制器(SourceTableView.class)
  • 第2项:具有目标nstableview(TargetTableView.class)的viewcontroller

我怎么能用这个项目做到这一点? 我知道如何在故事板中创建拆分视图控制器。 但我不知道,如果我有两个不同的类,如何类SourceTableView.class的iBoutlet SourceTabelView分配类TargetTableView.class的iBoutlet TargetTableView

更新

$date = \DateTime::createFromFormat('m/Y|', '02/2017');

NSManagedObject.class

var person = [Person]()

1 个答案:

答案 0 :(得分:2)

拆分视图内两个表视图之间的拖放示例。在一个表视图中拖动和多个选择将起作用。按住Option键拖动副本。

每个表视图的数据源是拆分视图中的视图控制器。每个表视图都有自己的视图控制器,每个视图控制器控制一个表视图。两个视图控制器都是相同的NSViewController子类:

class ViewController: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

    @IBOutlet weak var myTableView: NSTableView!
    var dataArray: NSMutableArray = ["John Doe", "Jane Doe", "Mary Jane"]

    override func viewDidLoad() {
        super.viewDidLoad()
        myTableView.register(forDraggedTypes: ["com.yoursite.yourproject.yourstringstype"])
    }

    override var representedObject: Any? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    // NSTableViewDataSource data methods

    func numberOfRows(in tableView: NSTableView) -> Int {
        return dataArray.count
    }

    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        return dataArray[row] as AnyObject!;
    }

    // NSTableViewDataSource drag methods

    func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
        // the dragging destination needs the strings of the rows to add to its own data,
        // we, the dragging source, need the indexes of the rows to remove the dropped rows.
        pboard.declareTypes(["com.yoursite.yourproject.yourstringstype", "com.yoursite.yourproject.yourindexestype"],
            owner: nil)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: (dataArray as NSArray).objects(at:rowIndexes as IndexSet)), forType: "com.yoursite.yourproject.yourstringstype")
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: rowIndexes), forType: "com.yoursite.yourproject.yourindexestype")
        return true
    }

    func tableView(_ tableView: NSTableView, draggingSession session: NSDraggingSession,
            endedAt screenPoint: NSPoint, operation: NSDragOperation) {
        // remove the dragged rows if the rows are dragged to the trash or were moved to somewhere else.
        var removeRows = false
        if operation == .delete {
            // trash
            removeRows = true
        } else if operation == .move {
            // check if the point where the rows were dropped is inside our table view.
            let windowRect = tableView.convert(tableView.bounds, to: nil)
            let screenRect = view.window!.convertToScreen(windowRect)
            if !NSPointInRect(screenPoint, screenRect) {
                removeRows = true
            }
        }
        if removeRows {
            // remove the rows, the indexes are on the pasteboard
            let data = session.draggingPasteboard.data(forType: "com.yoursite.yourproject.yourindexestype")!
            let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSIndexSet
            (dataArray as NSMutableArray).removeObjects(at: rowIndexes as IndexSet)
            tableView.reloadData()
        }
    }

    // NSTableViewDataSource drop methods

    func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, 
            proposedDropOperation dropOperation: NSTableViewDropOperation) -> NSDragOperation {
        // only accept drop above rows, not on rows.
        if dropOperation == .above {
            // return move if the dragging source allows move
            if info.draggingSourceOperationMask().contains(.move) {
                return .move
            }
            // return copy if the dragging source allows copy
            if info.draggingSourceOperationMask().contains(.copy) {
                return .copy
            }
        }
        return []
    }

    func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int,
            dropOperation: NSTableViewDropOperation) -> Bool {
        // if the rows were moved inside the same table view we do a reorder
        var dropRow = row
        if info.draggingSource() as AnyObject === myTableView as AnyObject &&
            info.draggingSourceOperationMask().contains(.move) {
            // remove the rows from their old position
            let data = info.draggingPasteboard().data(forType: "com.yoursite.yourproject.yourindexestype")!
            let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSIndexSet
            (dataArray as NSMutableArray).removeObjects(at: rowIndexes as IndexSet)
            // recalculate the row of the drop
            dropRow -= rowIndexes.countOfIndexes(in: NSMakeRange(0, dropRow))
        }
        // insert the dragged rows
        let data = info.draggingPasteboard().data(forType: "com.yoursite.yourproject.yourstringstype")!
        let draggedStrings = NSKeyedUnarchiver.unarchiveObject(with: data) as! [Any]
        dataArray.insert(draggedStrings, at:IndexSet(integersIn:dropRow..<(dropRow + draggedStrings.count)))
        tableView.reloadData()
        return true
    }

}

要拖动到垃圾箱工作,子类NSTableView并覆盖:

override func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor
        context: NSDraggingContext) -> NSDragOperation {
    let test = super.draggingSession(session, sourceOperationMaskFor: context)
    Swift.print("sourceOperationMaskFor \(test)")
    switch context {
        case .withinApplication:
            return [.move, .copy]
        case .outsideApplication:
            return [.delete]
    }
}

P.S。我不熟悉Swift并且在使用数组和索引集方面遇到了一些问题,因此我使用了NSMutableArrayNSIndexSet