I´m trying to populate a NSTableView
with a struct. The struct is getting it's data from Firebase. I have tried to replicate the way I would do it in iOS
but I'm not quite there yet.
var orders = [OrderModel]()
struct OrderModel {
var order: String!
var name: String?
var adress: String?
var email: String?
}
Read from Firebase:
ref?.child("orders").observe( .childAdded, with: { (snapshot) in
let dict = snapshot.value as? [String : AnyObject] ?? [:]
let newData = OrderModel(order: dict["order"] as? String, name: dict["name"] as? String, adress: dict["adress"] as? String, email: dict["email"] as? String
self.orders.append(newData)
})
Populate the NSTableView
:
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let userCell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "ordersCell"), owner: self) as? OrdersTableViewCell else { return nil }
//the object
let order: OrderModel
//getting the object of selected position
order = orders[row] //Error index out of range
userCell.orderLabel.stringValue = order.order ?? "Error getting order"
userCell.nameLabel.stringValue = order.name ?? "Error getting name"
userCell.adressLabel.stringValue = order.adress ?? "Error getting address"
return userCell
}
I don't know if the only problem here is this line:
order = orders[row] //Error index out of range
But that is where I'm at now.
Unlike in iOS in macOS there is a more sophisticated way to populate a table view: Cocoa Bindings. As you are using only one cell view for all data this is preferable.
First make your struct a class inheriting from NSObject
@objcMembers class OrderModel : NSObject { dynamic var order: String? dynamic var name: String? dynamic var adress: String? dynamic var email: String? init(order : String?, name : String?, adress : String?, email : String?) { self.order = order self.name = name self.adress = adress self.email = email } }
Delete the entire method tableView: viewFor: row:
Adopt NSTableViewDataSource
and NSTableViewDelegate
in the view controller
Implement these two methods in the view controller
func numberOfRows(in tableView: NSTableView) -> Int { return orders.count } func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { return orders[row] }
Select the storyboard or xib in the project navigator
Remove the identifier of the table cell view
Select the table view (not the scroll view!), press ⌥⌘7 to open the Connections Inspector and connect (control-drag) dataSource
and delegate
to the view controller
Select the Order text field in the table cell view. Make sure it is the text field.
Press ⌥⌘8 to open the Bindings Inspector
Click on the disclosure triangle next to Value
Check Bind To
-> Table Cell View
In Model Key Path enter objectValue.order
Do the same in the other text fields (replace order
with the other properties respectively)
In the view controller after receiving the data from Firebase reload the table view inside the closure on the main thread
self.orders.append(newData) DispatchQueue.main.async { self.tableView.reloadData() }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.