Thx for your answer.
I initialize the dataSource on the self (like often).
After that I set the tracks with a setter and I reload the datas :
`var tracks: [NSObject]? {
set {
datas = newValue
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak self] in
self!.tracksListTableView.reloadData() // to avoid the init bug...
}
}
get {
if let tracks: [NSObject] = datas as? [NSObject] {
return tracks
}
return nil
}
}`
My bad but my project has 2 years old and I don't even remember how I plug the datas to the TableView... In the inspector ?
Thx.
Post
Replies
Boosts
Views
Activity
I fill the tracks array with the setter I typed just before (with the reloadData) and then I have the NSTableViewDataSource extension to set the number of lines :
func numberOfRows(in tableView: NSTableView) -> Int {
if let tracks = tracks {
print("V&G_FW___numberOfRows : ", self, tracks.count)
return tracks.count
}
return 0
}
And in the NSTableViewDelegate extension I just get the tracks array for each track :
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if let theTracks: [ITLibMediaItem] = tracks as? [ITLibMediaItem] {
let theItem = theTracks[row]
let cellIdentifier: String = "TracksListCellID"
var text: String = ""
switch tableColumn?.identifier.rawValue {
case TableColumnID.trackNumberTableColumnID.rawValue:
text = String(row + 1)
case TableColumnID.titleTableColumnID.rawValue:
text = getTrackTitle(theTrack: theItem)
case TableColumnID.artistTableColumnID.rawValue:
text = iTunesModel.getArtistName(theITTrack: theItem)
case TableColumnID.albumTableColumnID.rawValue:
text = iTunesModel.getAlbumTitle(theITTrack: theItem)
case TableColumnID.locationTableColumnID.rawValue:
text = theItem.location?.path ?? ""
case TableColumnID.totalTimeTableColumnID.rawValue:
text = getTotalTime(theTrack: theItem)
default:
text = ""
}
if let cell: NSTableCellView = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: nil) as? NSTableCellView {
cell.textField!.stringValue = text
return cell
}
}
print("V&G_FW___viewFor tableColumn : ", self, "no TitleCellID is present !")
return nil
}
So classic code.
My problem is I think I need to call the reloadData each time I delete an item in the TableView at the bottom to refresh the view... Right ?
Alright, everything is OK with adding / removing programmatically but now I'd like to filter.
Since each time I change something in the array used by the NSTableView, I need to reloadData() the NSTableView, I guess it is the same when I want to filter the array, right ?
Thx.
Thx for your answer.
Another method is also to use a NSArrayController to bind programmatically to the NSTableView, right ?
With that method, is it easier ? Because from the moment I start to add/delete/filter, it becomes more complicated to reload the datas and get it like it is in the TableView, isn't it ?
So I start to change my code for the binding :
tracksListTableView.bind(.content, to: _arrayController, withKeyPath: "arrangedObjects", options: nil)
Like that, I don't have to reload the datas each time I add a track to the TableView. I just do :
_arrayController.add(theTrack)
But now I have to change my code to remove the selected tracks... What is the good way ?
Thx.
Ok so you never use NSArrayController, right ?
Yes.
Thx.
So I switched my little app with NSTableViews to NSArray to NSArrayCollection.
It is working but to get the number of items I still need to use a NSArray for the moment... I'd like to remove it and only use only the NSArrayCollection.
So for the viewFor tableColumn: NSTableColumn? (for example), I need to know how many objects are added in the NSCollectionView. I create it programmatically for information, not in IB.
Thx.
Also, I mean NSArrayController and not NSArrayCollection, my mistake...
Alright, it is working !
But now, how to get an item at index(n) ?
In the viewFor tableColumn: NSTableColumn?, the [row] method failed :
let theTracks = theArrayCollection.arrangedObjects as! [ITLibMediaItem]
let theTrack = theTracks[row] >>> fail ("NSArray element failed to match the Swift Array Element type")
Why ?
Thx.
Well, I think it is because I used the arrayController.add method instead of arrayController.addObject like in your example...
A dump like in your link in the iteration works better now.
Thx.
Thx for this tip.
And is it possible to add an entire array directly ?
Thx.
Back !
So I have the adding / removing actions. What about filtering ?
I'm using a NSArrayController now which has binding capacities. To bind it to the NSTableView, I simply do :
tracksListTableView.bind(.content, to: arrayController, withKeyPath: "arrangedObjects", options: nil)
Et voila !
I tried to bind the NSSearchField in the same way :
searchField.bind(
.predicate,
to: self.arrayController,
withKeyPath: NSBindingName.filterPredicate.rawValue,
options: [.predicateFormat: "col CONTAINS[cd] $value"]
But it fails when I start to type in the searchField :
Multiline
Error setting value for key path filterPredicate of object <NSArrayController: 0x6000036fc2a0>[object class: NSMutableDictionary, number of selected objects: 1] (from bound object <NSSearchField: 0x14c710d90>): [<ITLibMediaItem 0x600001013580> valueForUndefinedKey:]: this class is not key value coding-compliant for the key col.
How to fix that ?
Thx.
Hi,
Back on this post.
So I took a look on the Internet and I found some interesting sources.
I found how to bind the NSSearchField :
searchField.bind(.predicate, to: arrayController, withKeyPath: NSBindingName.filterPredicate.rawValue, options: [.predicateFormat: "title CONTAINS $value"])
And as U can see it works like a charm when I search in the ITMediaLibItem object title :
But I'm not familiar with the notation and I didn't find all the possibilities. I notice if I had [cd] to the CONTAINS keyword, whatever the case the string is which is great :
What are the other possibilities ?
Thx.
Hi,
A few mouths later, I just saw your answer... Thx for that !
I'm back on my project which use the ITLibrary (I'm speaking about it here)
Everything works like a charm with my NSSearchField and now I'd like to add a NSMenu to have a more option to filter.
I took a look to your link but I'm not sure to understand how to add the NSMenu...
I have to set a NSMenu to the cell of the NSSearchfield ?
Thx.
Hi,
So basically, I just added a NSMenu to my NSSearchField :
let theMenu = NSMenu(title: "Filters")
let theMenus = ["all", "artist", "title", "album"]
for theName in theMenus {
let theMenuItem = NSMenuItem(title: theName, action: nil, keyEquivalent: "")
theMenu.addItem(theMenuItem)
theMenuItem.isEnabled = true
}
searchField.searchMenuTemplate = theMenu
Problem : the items are disabled and I don't know how to enable it :
What's wrong ?
Thx.