I am writing a NSTableView based view. And I try to use:
let selectedRowNumber = tableViewMesos.selectedRow
and
let selectedColumnNumber = tableViewMesos.selectedColumn
to identify the textField that is in the cell View that I want to save into my array:
taulaDeConsumsMesos[selectedColumnNumber].filesConsum![selectedRowNumber] = sender.doubleValue
But a problem happens here, because the return value of selectedColumnNumber
is -1 which is the value of non-selected Column for any row selected of any column.
But the selectedRowNumber
returns the index of the row properly.
So the program crashes when finishing the edition of a textfield in a cell. Because the selectedColumnNumber is -1 out of the limits of the array. See the code below to identify where this happens exactly.
Could you help me? I lost too many hours on this.. I'm new on OSX programing I hope you could help me.
Here is the completed code:
class BalancGlobalViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate{
@IBOutlet weak var tableViewMesos: NSTableView!
let mesos = ColumnaDeConsumsMes() // contains an array of doubles called .filesConsum that represent the rows that I want to show
let consum = ColumnaDeConsumsMes()
var taulaDeConsumsMesos = [ColumnaDeConsumsMes]() // array of arrays that represent the columns with rows in it that will be the tableView data
func setUpMesos(){ // init table columns
mesos.filesConsum = [1, 2, 3, 4, 5, 6, 7, 8 , 9, 10, 11, 12, nil]
consum.filesConsum = [100, 100, 100, nil, nil, nil, nil, nil , nil, nil, nil, nil, nil]
taulaDeConsumsMesos.append(mesos)
taulaDeConsumsMesos.append(consum)
}
func setUpGradient(){
...not important here
}
override func viewDidLoad() {
super.viewDidLoad()
setUpMesos()
tableViewMesos.setDelegate(self)
tableViewMesos.setDataSource(self)
setUpGradient()
}
override func viewDidLayout() {
super.viewDidLayout()
setUpGradient()
}
@IBAction func alEditarUnTextFieldDeConsum(sender: NSTextField) { // this is the IBAction of the TextField of the Consum Column (see the image)
let selectedRowNumber = tableViewMesos.selectedRow
let selectedColumnNumber = tableViewMesos.selectedColumn
print("SelectedRowNumber! = \(selectedRowNumber)")
print("SelectedColumnNumber! = \(selectedColumnNumber)")
// the selectedColumnNumber return always -1 except when clicking the header of the column, then return 0 or 1 depending on the column. But it should return 0 even when the user edit a row of the index 0 column !!!
let numero = tableViewMesos.numberOfColumns
print("numero de columnes: \(numero)") // returns 2
if selectedRowNumber != -1 { //-1 is returned when no row is selected in the TableView
taulaDeConsumsMesos[selectedColumnNumber].filesConsum![selectedRowNumber] = sender.doubleValue //try to save here the value edited by the user on my array of arrays of doubles
//here the program crashes! selectedColumnNumber = -1
print("Sender! = \(sender.doubleValue)") // the sender returns the information correctly
//print("SelectedRowNumber! = \(selectedRowNumber)") // this works too!
reloadTaula()
}
}
func tableViewSelectionDidChange(notification: NSNotification) {
print("columna: \(tableViewMesos.selectedColumn)")
print("row: \(tableViewMesos.selectedRow)")
print("tag: \(tableViewMesos.selectedTag())")
}
// the tableViewMesos.selectedColumn return always -1 except when clicking the header of the colum, then return 0 or 1 depending on the column. But i should return 0 even when I edit a row of the index 0 column !!!
func reloadTaula() {
tableViewMesos.reloadData()
}
// MARK: - Datasource
func numberOfRowsInTableView(tableView: NSTableView) -> Int {
if (tableView.identifier == "TaulaMesos") {
return 13
}
}
// MARK: - Delegate
func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
var valorCela: Double
var cellIdentifier:String=""
if tableColumn == tableView.tableColumns[0] {
if taulaDeConsumsMesos[0].filesConsum![row] == nil {
return nil
}else {
valorCela = taulaDeConsumsMesos[0].filesConsum![row]!
cellIdentifier = "MesCellID"
}
} else {
if taulaDeConsumsMesos[1].filesConsum![row] == nil {
return nil
}else {
valorCela = taulaDeConsumsMesos[1].filesConsum![row]!
cellIdentifier = "ConsumCellID"
}
}
if let cell = tableView.makeViewWithIdentifier(cellIdentifier, owner: nil ) as? NSTableCellView {
cell.textField?.doubleValue = valorCela
return cell
}
return nil
}
}
Table views do not support selecting individual cells. Both styles of table view support selecting rows. Old-style NSCell
-based table views support selecting columns, but modern view-based table views no longer support selecting columns. But it would never have been the case that both selectedRow
and selectedColumn
were valid at the same time.
From the 10.7 AppKit release notes, where view-based table views were introduced:
Note that the View Based TableView does not support column selection.
To get the row and column of the cell whose text field sent the action, you should use tableViewMesos.rowForView(sender)
and tableViewMesos.columnForView(sender)
. Note, especially, that there's nothing guaranteeing that the text field that's sending the action method is in a selected row. So, don't think of it as selected. It's just the one that's been manipulated by the user.