0

为简单起见,我使用此 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 双击编辑单元格: 双击 Cocoa 中的 NSTableView 行?

如果表格有多个列,要确定正在编辑哪一列,我必须向 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 和 DraggingSessionendedAt 被调用,但 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 中)、拖放以及选择了哪个弹出按钮的任何建议?

谢谢。

4

1 回答 1

0

如果您将类型更改为 ,您将保存一些代码MyRowTypeNSPasteboard.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可能是适当的位置。

于 2018-04-05T04:03:51.717 回答