问题
I am trying to remove a row from my NStableView by swipe function. I am using macOS 10.13 and swift 4 and pretty new to swift coding.
I tried to follow: Implementing NSTableViewRowAction using Swift but it did not work for me.
And this is how I implement it:
public func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
// left swipe
if edge == .trailing {
let deleteAction = NSTableViewRowAction(style: .destructive, title: "Delete", handler: { (rowAction, row) in
// action code
List_Symbol.remove(at: row)
List_Price.remove(at: row)
List_Procent.remove(at: row)
List_Volume.remove(at: row)
})
deleteAction.backgroundColor = NSColor.red
return [deleteAction]
}
let archiveAction = NSTableViewRowAction(style: .regular, title: "Archive", handler: { (rowAction, row) in
// action code
})
return [archiveAction]
}
Any other suggestion how to delete row in NSTableView by swiping?
The Whole code:
import Cocoa
import Alamofire
var List_Symbol = ["AAPL"]
var List_Price = [10.0]
var List_Procent = [1.0]
var List_Volume = [100]
class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
@IBOutlet weak var tableView: NSTableView!
@IBOutlet weak var input: NSTextField!
@IBAction func additem(_ sender: Any) {
if (input.stringValue != ""){
var Stock = StockInformation(symbol: input.stringValue)
Stock.GetStockInformation {
List_Symbol.append(Stock.Symbol)
List_Price.append(Stock.Price)
List_Procent.append(Stock.Percent)
List_Volume.append(Stock.Volume)
self.tableView.reloadData()
}
input.stringValue = ""
}
self.tableView.reloadData()
}
public func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
// left swipe
if edge == .trailing {
let deleteAction = NSTableViewRowAction(style: .destructive, title: "Delete", handler: { (rowAction, row) in
// action code
List_Symbol.remove(at: row)
List_Price.remove(at: row)
List_Procent.remove(at: row)
List_Volume.remove(at: row)
tableView.removeRows(at: IndexSet(integer: row), withAnimation: .effectFade)
})
deleteAction.backgroundColor = NSColor.red
return [deleteAction]
}
let archiveAction = NSTableViewRowAction(style: .regular, title: "Archive", handler: { (rowAction, row) in
// action code
})
return [archiveAction]
}
override func viewDidAppear() {
tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfRows(in tableView: NSTableView) -> Int{
return List_Symbol.count
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any?{
var identifierStr = tableColumn!.identifier
if (identifierStr.rawValue == "StockNameCellID"){
return List_Symbol[row]
}else if (identifierStr.rawValue == "PriceCellID"){
return List_Price[row]
}else if (identifierStr.rawValue == "PercentCellID"){
return List_Procent[row]
}else if (identifierStr.rawValue == "VolumeCellID"){
return List_Volume[row]
}
tableView.reloadData()
return nil
}
}
回答1:
Don't use multiple arrays as data source, that's horrible.
In macOS you can replace a lot of boilerplate code with Cocoa Bindings
• Use a class inherited from NSObject
as data source
@objcMembers
class Stock : NSObject {
dynamic var symbol : String
dynamic var price : Double
dynamic var procent : Double
dynamic var volume : Int
init(symbol : String, price : Double, procent : Double, volume : Int) {
self.symbol = symbol
self.price = price
self.procent = procent
self.volume = volume
}
}
• Declare the data source array within the view controller
@objc var stocks = [Stock]()
• In additem
create a new Stock
item, rather then reloading the table view insert only the row with a smart animation
@IBAction func additem(_ sender: Any) {
if !input.stringValue.isEmpty {
let stock = StockInformation(symbol: input.stringValue)
stock.GetStockInformation {
let newStock = Stock(symbol: stock.Symbol, price: stock.Price, procent: stock.Percent, volume: stock.Volume)
let insertionIndex = IndexSet(integer: stocks.count)
self.stocks.append(newStock)
self.tableView.insertRows(at: insertionIndex, withAnimation: .effectGap)
self.input.stringValue = ""
}
}
}
• objectValueFor
and numberOfRows
are only one line respectively
func numberOfRows(in tableView: NSTableView) -> Int{
return stocks.count
}
func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
return stocks[row]
}
• The delete
action is
public func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
print("swipe")
// left swipe
if edge == .trailing {
let deleteAction = NSTableViewRowAction(style: .destructive, title: "Delete", handler: { (rowAction, row) in
// action code
self.stocks.remove(at: row)
tableView.removeRows(at: IndexSet(integer: row), withAnimation: .effectFade)
})
deleteAction.backgroundColor = NSColor.red
return [deleteAction]
}
}
• In Interface Builder connect datasource and delegate of the table view to the view controller. Further press ⌥⌘7 (Bindings Inspector), then select each Table View Cell
(the NSTextField
not NSTextFieldCell
and not Table Cell View
!) and bind the Value
to Table Cell View
and Model Key Path
to the corresponding property (objectValue.symbol
, objectValue.price
etc.)
You can even use more Cocoa Bindings
by binding the content
of the table view to the stocks
array. Then you can get rid of the datasource and its methods.
来源:https://stackoverflow.com/questions/51692877/remove-row-from-nstableview-by-swiping