I am implementing a drag and drop to reorder the cell, everything works but I would like that during dragging the cell view follows the mouse.
I'm using NSTableRowView. I need to make it work with NSTableRowView. If you have an idea how to do ..
The actually result:
My actually code:
public func tableView(_ tableView: NSTableView, pasteboardWriterForRow row: Int) -> NSPasteboardWriting? {
let account = viewModel.formattedServices[row]
let pasteboardItem = NSPasteboardItem()
pasteboardItem.setString(account.id, forType: NSPasteboard.PasteboardType(rawValue: "mymoney.account"))
return pasteboardItem
}
public func tableView(_ tableView: NSTableView, validateDrop info: NSDraggingInfo, proposedRow row: Int, proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {
if dropOperation == .above {
return .move
} else {
return []
}
}
public func tableView(_ tableView: NSTableView, acceptDrop info: NSDraggingInfo, row: Int, dropOperation: NSTableView.DropOperation) -> Bool {
guard let item = info.draggingPasteboard.pasteboardItems?.first,
let theString = item.string(forType: NSPasteboard.PasteboardType(rawValue: "mymoney.account")),
let account = viewModel.formattedServices.first(where: { $0.id == theString }),
let originalRow = viewModel.formattedServices.firstIndex(where: { $0.id == account.id })
else { return false }
var newRow = row
// When you drag an item downwards, the "new row" index is actually --1. Remember dragging operation is `.above`.
if originalRow < newRow {
newRow = row - 1
}
// Animate the rows
tableView.beginUpdates()
tableView.moveRow(at: originalRow, to: newRow)
tableView.endUpdates()
return true
}
I can't find a method to return the cell view during dragging.
For return cell view I'm using func tableView(_ tableView: NSTableView, rowViewForRow row: Int) -> NSTableRowView?
And my NSTableRowView
:
class ServicesTableViewCell: NSTableRowView, CustomCelleable {
@IBOutlet weak var titleLbl: NSTextField!
@IBOutlet weak var notificationCount: NSButton!
@IBOutlet weak var iconImageView: NSImageView!
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
isEmphasized = false
}
func setup(with item: Celleable) { }
Step 1 NSTableRowView
can't replace NSTableCellView
, use NSTableCellView
for the table cells.
Starting with the test app. In IB, select the column in the table view and add a Text Table Cell View from the library.
In ViewController.swift replace tableView(_:rowViewForRow:)
by tableView(_:viewFor:row:)
.
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let cell = tableView.makeView(withIdentifier: tableColumn!.identifier, owner: self) as? NSTableCellView else {
fatalError()
}
cell.textField?.stringValue = array[row].name
return cell
}
In setTableView()
remove registering the nib.
func setTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.registerForDraggedTypes([NSPasteboard.PasteboardType(rawValue: "mymoney.account")])
}
ServicesTableViewCell isn’t used anymore.
Step 2 Use a subclass of NSTableRowView
to disable isEmphasized
:
Add a subclass of NSTableRowView
, let’s name it ServicesTableRowView
.
Override isEmphasized
to make it always false
.
class ServicesTableRowView: NSTableRowView {
override var isEmphasized: Bool {
get {
return false
}
set {
// do nothing
}
}
}
In IB select the table view and add a Custom View from the library. Set the class of the view to ServicesTableRowView
and the identifier to NSTableViewRowViewKey
.
The modified test project: we.tl/t-yjpZrz6q7g