nstableview拖放自定义单元格视图

时间:2017-06-11 19:45:00

标签: ios cocoa swift3 drag-and-drop tableview

我使用swift 3 for osx,我正在不同的视图控制器中搜索两个NSTableViews之间的拖放解决方案。

我有一个简单的工作解决方案,每个tableview只有一列,没有自定义单元格视图和字符串值。

SourceTableView

width of containing box - left - right

TargetTableView

import Cocoa

class SourceTableView: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

    @IBOutlet weak var leftTableView: NSTableView!
    var dataArray: NSMutableArray = ["Item 1","Item 2","Item 3"]
    let pbStringType = "NSPasteBoardStringType"
    let pbIndexType = "NSPasteBoardIndexType"


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

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


    func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
        let data = (dataArray as NSArray).objects(at:rowIndexes as IndexSet)
        pboard.declareTypes([pbStringType, pbIndexType], owner: nil)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: data), forType: pbStringType)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: rowIndexes), forType: pbIndexType)
        return true
    }
}

但是现在我需要针对以下情况的解决方案:

  • SourceTableView>一列>自定义单元格视图>每个单元格的值:firstName,secondName
  • TargetTableView>三列>自定义单元格视图>每个单元格的值:firstName,secondName,Age

我通过核心数据获得的值:

import Cocoa

class TargetVC2: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

    @IBOutlet weak var rightTableView: NSTableView!
    var dataArray: NSMutableArray = ["Item 5", "Item 6", "Item 7"]
    let pbStringType = "NSPasteBoardStringType"
    let pbIndexType = "NSPasteBoardIndexType"


    override func viewDidLoad() {
        super.viewDidLoad()
        rightTableView.register(forDraggedTypes: [pbStringType])
    }


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

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



    func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
        let data = dataArray.objects(at:rowIndexes as IndexSet)
        pboard.declareTypes([pbStringType, pbIndexType], owner: nil)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: data), forType: pbStringType)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: rowIndexes), forType: pbIndexType)
        return true
    }




    func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableViewDropOperation) -> NSDragOperation {

        if dropOperation == .above {
            return .move
        }
        return []
    }





    func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableViewDropOperation) -> Bool {

        var dropRow = row
        if info.draggingSource() as! NSTableView == rightTableView && tableView == rightTableView && dropOperation == .above  {
            let data = info.draggingPasteboard().data(forType: pbIndexType)!
            let rowIndexes = NSKeyedUnarchiver.unarchiveObject(with: data) as! NSIndexSet
            dataArray.removeObjects(at: rowIndexes as IndexSet)
            dropRow -= rowIndexes.countOfIndexes(in: NSMakeRange(0, dropRow))
        }

        let data = info.draggingPasteboard().data(forType: pbStringType)!
        let draggedStrings = NSKeyedUnarchiver.unarchiveObject(with: data) as! [Any]
        dataArray.insert(draggedStrings, at:IndexSet(integersIn:dropRow..<(dropRow + draggedStrings.count)))
        rightTableView.reloadData()
        return true
    }

}

但我的上述解决方案并不适用于我的新#34;愿望方案&#34;

更新 例如:我修改了我的SourceTabelView:

func requestValues() {
   var values= [Person]()
   let appdelegate = NSApplication.shared().delegate as! AppDelegate
   let context = appdelegate.persistentContainer.viewContext
   let request = NSFetchRequest<Person>(entityName: "Person")

   do {
      values = try context.fetch(request)
      SourceTableView.reloadData()
   } catch { }
}

它工作正常,但如果我拖动行的值为&#34; Max&#34; =&GT;我的应用程序因此错误而崩溃:

import Cocoa

struct structData {
    var firstname:String
    var secondname:String
}

class SourceVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {

    @IBOutlet weak var leftTableView: NSTableView!
    var people = [structData]()
    let pbStringType = "NSPasteBoardStringType"
    let pbIndexType = "NSPasteBoardIndexType"

    override func viewDidLoad() {
        people.append(structData(firstname:"Max",secondname:"Mustermann"))
    }


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

    func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
        return people[row].firstname
    }


    func tableView(_ tableView: NSTableView, writeRowsWith rowIndexes: IndexSet, to pboard: NSPasteboard) -> Bool {
        let data = (people as NSArray).objects(at:rowIndexes as IndexSet)
        pboard.declareTypes([pbStringType, pbIndexType], owner: nil)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: data), forType: pbStringType)
        pboard.setData(NSKeyedArchiver.archivedData(withRootObject: rowIndexes), forType: pbIndexType)
        return true
    }
}

1 个答案:

答案 0 :(得分:3)

崩溃的原因看起来,Swift运行时无法为您的结构类型找到encodeWithCoder。

您可能需要实现encodeWithCoder。您的structData结构应符合encodeWithCoder。

请查看以下有关如何执行相同操作的链接

  

Example-1 Example-2 Example-3