2017-06-11 6 views
5

Ich arbeite mit Swift 3 für Osx und ich suche nach einer Drag-and-Drop-Lösung zwischen zwei NSTableViews in verschiedenen View-Controllern.nstableview Ziehen und Ablegen mit benutzerdefinierten Zellenansichten

Ich habe eine einfache funktionierende Lösung für den Fall, dass jede Tabellenansicht nur eine Spalte, keine benutzerdefinierten Zellansicht und String-Werte hat.

SourceTableView

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

TargetTableView

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 
    } 

} 

Aber jetzt brauche ich eine Lösung für den folgenden Fall:

  • SourceTableView> eine Spalte> benutzerdefinierte Zelle Ansicht> val ues pro Zelle: vorName, secondName
  • TargetTableView> drei Spalten> benutzerdefinierte Zelle Ansicht> Werte pro Zelle: vorName, secondName, Alter

die Werte, die ich über Kerndaten erhalten:

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

Aber meine Lösung oben funktioniert nicht mit meinem neuen „Wunschszenario“

UPDATE Zum Beispiel: I modifizierte meine SourceTabelView wie folgt aus:

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

Es funktioniert gut, aber wenn ich ziehen Sie die Zeile mit dem Wert „Max“ => meine app stürzt mit diesem Fehler:

2017-06-12 07:51:09.096744+0200 TableView-DragDrop[10315:1489730] -[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x6080000910d0 
2017-06-12 07:51:09.100198+0200 TableView-DragDrop[10315:1489730] [General] -[_SwiftValue encodeWithCoder:]: unrecognized selector sent to instance 0x6080000910d0 
2017-06-12 07:51:09.129238+0200 TableView-DragDrop[10315:1489730] [General] (
    0 CoreFoundation      0x00007fffaf4d657b __exceptionPreprocess + 171 
    1 libobjc.A.dylib      0x00007fffc489a1da objc_exception_throw + 48 
    2 CoreFoundation      0x00007fffaf556f14 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132 
    3 CoreFoundation      0x00007fffaf449c93 ___forwarding___ + 1059 
    4 CoreFoundation      0x00007fffaf4497e8 _CF_forwarding_prep_0 + 120 
    5 Foundation       0x00007fffb0ed695a _encodeObject + 1241 
    6 Foundation       0x00007fffb0ed7f0c -[NSKeyedArchiver _encodeArrayOfObjects:forKey:] + 460 
    7 Foundation       0x00007fffb0ed695a _encodeObject + 1241 
    8 Foundation       0x00007fffb0f12492 +[NSKeyedArchiver archivedDataWithRootObject:] + 156 
    9 TableView-DragDrop     0x00000001000029a3 _TFC18TableView_DragDrop8SourceVC9tableViewfTCSo11NSTableView13writeRowsWithV10Foundation8IndexSet2toCSo12NSPasteboard_Sb + 915 
    10 TableView-DragDrop     0x0000000100002e5c _TToFC18TableView_DragDrop8SourceVC9tableViewfTCSo11NSTableView13writeRowsWithV10Foundation8IndexSet2toCSo12NSPasteboard_Sb + 108 
    11 AppKit        0x00007fffad6fc109 -[NSTableView _sendDataSourceWriteDragDataWithIndexes:toPasteboard:] + 102 
    12 AppKit        0x00007fffad6fcd06 -[NSTableView _performClassicDragOfIndexes:hitRow:event:] + 180 
    13 AppKit        0x00007fffad21e7b5 -[NSTableView _performDragFromMouseDown:] + 468 
    14 AppKit        0x00007fffad21cadf -[NSTableView mouseDown:] + 735 
    15 AppKit        0x00007fffad84024f -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 6341 
    16 AppKit        0x00007fffad83ca6c -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 1942 
    17 AppKit        0x00007fffad83bf0a -[NSWindow(NSEventRouting) sendEvent:] + 541 
    18 AppKit        0x00007fffad6c0681 -[NSApplication(NSEvent) sendEvent:] + 1145 
    19 AppKit        0x00007fffacf3b427 -[NSApplication run] + 1002 
    20 AppKit        0x00007fffacf05e0e NSApplicationMain + 1237 
    21 TableView-DragDrop     0x000000010000444d main + 13 
    22 libdyld.dylib      0x00007fffc517b235 start + 1 
    23 ???         0x0000000000000003 0x0 + 3 
) 
2017-06-12 07:51:09.148230+0200 TableView-DragDrop[10315:1489730] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it. 
+0

hey zu tun. Hat die folgende Antwort das Problem gelöst? Wenn ja, bitte akzeptieren Sie es als Antwort. –

Antwort

3

Der Grund für die Crash-Optik Die Swift-Laufzeitumgebung kann z. B. encodeWithCoder für Ihren Strukturtyp nicht finden.

Möglicherweise müssen Sie encodeWithCoder implementieren. Ihre structData-Struktur sollte mit encodeWithCoder übereinstimmen.

haben Sie einen Blick auf folgende Links, wie die gleiche

Example-1 Example-2 Example-3

+0

vielleicht hilft es. aber kann es nicht in mein Projekt realisieren :( – Ghost108

+0

Wo ist die Schwierigkeit? –

Verwandte Themen