I need to access to values of my cell based TableView from another controller. I do this code in my main controller and the tableView is in a child controller.
Here is what I do but I'm getting nil ...
// First grab the tableView controller
let myTableViewController = self.children[0] as! MyTableViewController
// Now I want to access the first row to get values of the textFields
let firstRowView = myTableViewController.theTable.rowView(atRow: 0, makeIfNecessary: true)
//Let's try another way :
let firstView = myTableViewController.theTable.view(atColumn: 0, row: 0, makeIfNecessary: true)
//I can't do more because "firstRowView" and "firstView " are nil
What I want is an array that contains all string of the table like :
let array1 = ["Peter","Quinn","1","387","49"]
EDIT :
I tried with a view base tableView, it works, I can get the textFields in my array.
But if edit a textfield by clicking ont it (changing "Peter" by "Franck"), it doesn't work, the NSTextField disappears in the debug utility...
let firstRowView = myTableViewController.theTable.rowView(atRow: 0, makeIfNecessary: true)?.subviews // return the first TableView
let textFields = firstRowView!.map { $0.subviews } as! [[NSTextField]]
let texts = textFields.map {$0.first!.stringValue}
print(texts) // let array1 = ["Peter","Quinn","1","387","49"]
Why I doesn't work anymore if I change manually a text ?
Here is what "firstRowView" contains when I don't manually edit a cell :
And here is what "firstRowView" contains when I manually edit a cell and it crashed :
You can see the NSTableCellView is transformed into NSView and my textField has disappeared... (it's still there in UI of course...)
First of all never get data from the view (the table view), get it from the model (the data source array).
In macOS there is a very convenient way. Use Cocoa Bindings and a view based table view. Apart from the model there's almost no code needed.
Create a model, a class inheriting from NSObject
is mandatory to take advantage of Key-Value Coding
@objcMembers
class Person : NSObject {
dynamic var firstName, lastName : String
dynamic var age : Int
dynamic var number1, number2 : Int
init(firstName : String, lastName : String, age : Int, number1 : Int, number2 : Int) {
self.firstName = firstName
self.lastName = lastName
self.age = age
self.number1 = number1
self.number2 = number2
}
}
Declare a data source array
@objc dynamic var people = [Person]()
and populate it
override func viewDidLoad() {
super.viewDidLoad()
people = [Person(firstName: "Peter", lastName: "Quinn", age: 1, number1: 387, number2: 49),
Person(firstName: "Peter", lastName: "Quinn", age: 1, number1: 387, number2: 49)]
}
That's the entire code. Now do the bindings.
In Interface Builder first select the table view (the easiest way is to ⌃⇧-click into the table view area and select Table View), go to Bindings Inspector (press ⌥⌘7) and bind the Content to View Controller
and set Model Key Path to people
.
Then select the text fields one by one – again ⌃⇧-click on each text field in the table view and select Table View Cell – and bind the Value to Table Cell View
and set Model Key Path to objectValue.<property>
for example
That's all. All changes in the table view (for example editing a field) are synchronized with the model. If you want to get the first name of the second entry just write
let secondFirstName = people[1].firstName