Как отсортировать NSTableView в Swift с помощью sortDescriptors?

#cocoa #sorting #swift #nstableview

#cocoa #сортировка #swift #nstableview

Вопрос:

Я использую view-based NSTableView в своем приложении Cocoa, написанном на Swift, и хочу реализовать функцию сортировки по двум столбцам таблицы. Однако в Objective-C это можно реализовать, сначала установив «Ключ сортировки» в инспекторе атрибутов, а затем внедрив метод делегирования источника данных с именем tableView: sortDescriptorsDidChange: .

Однако этот метод принимает sortDescriptor в качестве параметра и позволяет разработчикам использовать его внутри метода, например:

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

Однако в Swift Array нет такого метода, как sortUsingDescriptors . Итак, сначала я попытался преобразовать Array в NSMutableArray , чтобы использовать метод NSMutableArray ‘s, но поскольку мой массив Swift определен как AnyObject[] , его нельзя преобразовать в NSMutableArray .

Итак, как мне реализовать функциональность сортировки в табличном представлении в Swift? Я знаю, что Swift Array может использовать sort функцию для сортировки объекта путем сравнения двух аргументов и возврата значений bool, но можно ли ее использовать sortDescriptors для сортировки таблицы? Или я должен просто игнорировать sortDescriptors аргумент и вместо этого написать свою собственную логику сортировки вручную? (но тогда я не знаю, как определить, на какой столбец нажат, без sortDescriptors значения).

Ответ №1:

Вероятно, лучший способ, по крайней мере прямо сейчас, сначала преобразовать его в NSMutableArray , а затем отсортировать с помощью NSMutableArray sortUsingDescriptors метода и, наконец, преобразовать его обратно в исходный массив, вот так:

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

Кстати, var songsAsMutableArray = songs as NSMutableArray вызывает ошибку: NSArray is not a subtype of NSMutableArray , поэтому я создал NSMutableArray экземпляр, как показано выше.

Комментарии:

1. Я тоже пришел к этому решению, но все новые Swift (что за название, быстро меняющий свой синтаксис изо дня в день) теперь поставляются с *** NSForwarding: warning: object 0x.. of class '...' does not implement methodSignatureForSelector: -- trouble ahead . Попытка добавить этот метод приводит к появлению еще более неудобных сообщений. Ваш код все еще работает?

2. Неважно. Понял это сразу после комментария: просто используйте YourArray.sort, правильно обрамляя старые описания.

3. Успешно сделал это в Swift 4 — небольшая модификация, теперь это «сортировка (с использованием: дескрипторов)». Итак, с моим массивом данных о версиях, хранящихся в моем классе «IdbVersionInfo», это выглядит так: func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) { if versions != nil { let versionsAsNSMutable = NSMutableArray(array: versions!) versionsAsNSMutable.sort(using: table.sortDescriptors) versions = versionsAsNSMutable as? Array<IdbVersionInfo> } tableView.reloadData() } Отлично работает!