为了简单起见,我使用此URL在Swift(4.1)中创建一个macOS表: https://medium.com/@kicsipixel/very-simple-view-based-nstableview-in-swift-ab6d7bb30fbb
然后我使用此URL可以在表格中拖放行: http://bit.boutique/blog/2015/6/8/drag-sorting-nstableview-rows-in-swift/
我可以使用此URL确定如何双击以编辑单元格: Double click an NSTableView row in Cocoa?
如果表有多列,要确定正在编辑的列,我必须向Apple打开一个问题请求。他们向我提供了这段未记录的代码(并建议我打开一份文档错误报告,我做过)。
func control(_ control: NSControl, textShouldEndEditing fieldEditor: NSText) -> Bool {
print("textShouldEndEditing text is " + (fieldEditor.string) + " [" + String(describing: tableView.row(for: control)) + "][" + String(describing: tableView.column(for: control) ) + "]" )
return true
} // textShouldEndEditing
我将所有这些拼凑在一起,我以为我已经完成了。然后我尝试在我的表中添加另一列,一个NSPopUpButton。当我这样做时,表格显示正常但我不能再拖放行。
函数viewFor,writeRowsWith和DraggingSession endsAt被调用但是 validateDrop和acceptDrop不是。
// MARK: tableView
func numberOfRows(in tableView: NSTableView) -> Int {
tableView.doubleAction = #selector(doubleClickOnResultRow)
initPrefs()
tableView.tableColumns[0].title = localizedString(forKey: "CityNames_") + ":"
tableView.tableColumns[1].title = localizedString(forKey: "CityDisplayNames_") + ":"
tableView.tableColumns[2].title = localizedString(forKey: "weatherSource_") + ":"
tableView.tableColumns[3].title = localizedString(forKey: "API Key 1:_")
tableView.tableColumns[4].title = localizedString(forKey: "API Key 2:_")
return locationInformationArray.count
} // numberOfRows
// Populate table
func tableView(_ tableView: NSTableView,
viewFor tableColumn: NSTableColumn?,
row: Int) -> NSView? {
var cell: NSTableCellView
//print("viewFor: row=" + String(describing: row), column=" + String(describing: column) )
var column = -1
if tableColumn == tableView.tableColumns[0] {
column = 0
} else if tableColumn == tableView.tableColumns[1] {
column = 1
} else if tableColumn == tableView.tableColumns[2] {
column = 2
} else if tableColumn == tableView.tableColumns[3] {
column = 3
} else {
column = 4
}
if (column != 2) {
cell = (tableView.makeView(withIdentifier: tableColumn!.identifier, owner: nil) as? NSTableCellView)!
cell.textField?.stringValue = locationInformationArray[row][column]
} else { // Column 2/Weather Source
let result = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "weatherSource"), owner: nil) as! NSPopUpButton
InitWeatherSourceButton(weatherSourceButton: result)
result.selectItem(at: Int(locationInformationArray[row][column])!)
return result
}
return cell
} // viewFor (Populate)
// Drag "from"
func tableView(_ tableView: NSTableView,
writeRowsWith writeRowsWithIndexes: IndexSet,
to toPasteboard: NSPasteboard) -> Bool {
print("in writeRowsWith")
let data = NSKeyedArchiver.archivedData(withRootObject: [writeRowsWithIndexes])
toPasteboard.declareTypes([NSPasteboard.PasteboardType(rawValue: MyRowType)], owner:self)
toPasteboard.setData(data, forType:NSPasteboard.PasteboardType(rawValue: MyRowType))
return true
} // writeRowsWith (From Row)
// Drag "to"
func tableView(_ tableView: NSTableView,
validateDrop info: NSDraggingInfo,
proposedRow row: Int,
proposedDropOperation dropOperation: NSTableView.DropOperation) -> NSDragOperation {
print("in validateDrop, proposedRow=" + String(describing: row))
tableView.setDropRow(row, dropOperation: NSTableView.DropOperation.above)
return NSDragOperation.move
} // validateDrop
// Drag "to"
func tableView(_ tableView: NSTableView,
acceptDrop info: NSDraggingInfo,
row: Int,
dropOperation: NSTableView.DropOperation) -> Bool {
print("in acceptDrop, row=" + String(describing: row))
let pasteboard = info.draggingPasteboard()
let rowData = pasteboard.data(forType: NSPasteboard.PasteboardType(rawValue: MyRowType))
if(rowData != nil) {
var dataArray = NSKeyedUnarchiver.unarchiveObject(with: rowData!) as! Array<IndexSet>,
indexSet = dataArray[0]
let movingFromIndex = indexSet.first
//tableView.moveRow(at: movingFromIndex!, to: row) // Can only be done if the Array doesn't need to get re-populated
_moveItem(from: movingFromIndex!, to: row, array: &locationInformationArray)
tableView.reloadData()
return true
}
else {
return false
}
} // acceptDrop
func tableView(_ tableView: NSTableView,
draggingSession session: NSDraggingSession,
endedAt screenPoint: NSPoint,
operation: NSDragOperation) {
return
}
// Move row in table array
func _moveItem(from: Int,
to: Int,
array: inout [[String]]) {
//print("in _moveItem")
let item = array[from]
array.remove(at: from)
if(to > array.endIndex) {
array.append(item)
}
else {
array.insert(item, at: to)
}
} // _moveItem
最后,我无法确定NSPopUpButton正在访问哪一行(和列):
@IBAction func popUpSelectionDidChange(_ sender: NSPopUpButton) {
print("Selected item=" + String(describing: sender.indexOfSelectedItem) + " [" + String(describing: tableView.row(for: tableView)) + "][" + String(describing: tableView.column(for: tableView)) + "]" )
}
行和列都始终为-1。
有关如何解决我的剩余问题(在Swift中),拖放以及选择了哪个弹出按钮的任何建议?
感谢。
答案 0 :(得分:0)
如果您将MyRowType
的类型更改为NSPasteboard.PasteboardType
,则会保存一些代码,例如
fileprivate let MyRowType = NSPasteboard.PasteboardType("com.ed-danley.MyRowType")
tableView:writeRowsWithIndexes:toPasteboard:
和tableView:draggingSession:endedAtPoint:
消息用于拖动源支持(选中NSTableView.h
进行验证)。
tableView:validateDrop:proposedRow:proposedDropOperation:
和tableView:acceptDrop:row:dropOperation:
消息用于拖动目标支持。我的猜测是你没有将表配置为拖动目的地。
要将表格视图配置为拖动目标,您必须调用tableView.registerForDraggedTypes([MyRowType])
。这实际上是NSView
上的一个方法,它告诉AppKit您希望此视图成为拖动目标。您只需在表格视图中调用一次,因此根据您使用的控制器类型,viewDidLoad
或windowDidLoad
可能是合适的位置。