如何使用Swift

时间:2018-04-03 03:10:34

标签: swift macos nstableview nspopupbutton nstablecellview

为了简单起见,我使用此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中),拖放以及选择了哪个弹出按钮的任何建议?

感谢。

1 个答案:

答案 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您希望此视图成为拖动目标。您只需在表格视图中调用一次,因此根据您使用的控制器类型,viewDidLoadwindowDidLoad可能是合适的位置。