2

I use view-based NSTableView in my Cocoa app which is written in Swift, and want to implement a sort functionality on two table columns. However, in Objective-C, you can implement it by first setting the "Sort Key" in Attribute Inspector, and then implement the data source delegate method named tableView: sortDescriptorsDidChange:.

However, this method takes sortDescriptor as a parameter and lets developers use it within the method, like so:

- (void) tableView:( NSTableView *) tableView sortDescriptorsDidChange:( NSArray *) oldDescriptors { 
    [self.songs sortUsingDescriptors:tableView.sortDescriptors]; 
    [tableView reloadData]; 
}

However, in Swift Array, there are no such method as sortUsingDescriptors. So I first tried to convert Array to NSMutableArray in order to use the NSMutableArray's method, but since my Swift Array is defined as AnyObject[], it cannot be casted to NSMutableArray.

So how should I implement the sort functionality to the table view in Swift? I know Swift Array can use sort function to sort the object by comparing the two arguments and returning bool values, but is it possible to use sortDescriptors to sort the table? Or should I just ignore the sortDescriptors argument and instead write my own sort logic manually? (but then I don't know how to tell what column is clicked without the sortDescriptors value).

Blaszard
  • 30,954
  • 51
  • 153
  • 233

1 Answers1

2

Probably the best way, at least right now, is to first convert it to NSMutableArray and then sort it using NSMutableArray's sortUsingDescriptors method, and finally convert it back to the original Array, like so:

func tableView(tableView: NSTableView!, sortDescriptorsDidChange oldDescriptors: [AnyObject]) {
    var songsAsMutableArray = NSMutableArray(array: songs)
    songsAsNSMutableArray.sortUsingDescriptors(tableView.sortDescriptors)
    songs = songsAsNSMutableArray
    tableView.reloadData()
}

By the way, var songsAsMutableArray = songs as NSMutableArray causes an error: NSArray is not a subtype of NSMutableArray, so I created an NSMutableArray instance as shown above.

Blaszard
  • 30,954
  • 51
  • 153
  • 233
  • I also came to that solution, but all new Swift (what a name, swiftly changing its syntax from day to day) now comes with `*** NSForwarding: warning: object 0x.. of class '...' does not implement methodSignatureForSelector: -- trouble ahead`. Trying to add this method brings even more awkward messages. Does your code still work? – qwerty_so Jul 17 '16 at 20:23
  • Never mind. Figured it out right after commenting: Just use yourArray.sort with casing the oldDescriptors the right way. – qwerty_so Jul 17 '16 at 20:29
  • Successfully did this in Swift 4 - slight modification that it's now "sort(using: descriptors)". So with my array of version data stored in my "IdbVersionInfo" class, it looks like: `func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) { if versions != nil { let versionsAsNSMutable = NSMutableArray(array: versions!) versionsAsNSMutable.sort(using: table.sortDescriptors) versions = versionsAsNSMutable as? Array } tableView.reloadData() }` Works great! – Apollo Grace Feb 19 '18 at 18:43