How can I remove the sort indicator from an NSTableView that allows sorting? I am working in Xcode 8.3.x and programming with Swift 3 for macOS.
I have an NSTableView as a property of an NSViewController. I have implemented sorting when the user clicks on a Title cell. This all works as expected.
When the table is first loaded, it is unsorted and there is no sort indicator visible (this is desired behavior). After a title cell has been clicked, the data is properly sorted and a sort indicator is added to the header cell. Again all good so far.
Now I have a button to reload the unsorted table. Clicking the button does successfully reload the data (unsorted), but the sort indicator is still present (but misleading). I would like to remove the sort indicator when the "load unsorted" button is pressed because the indicator is now wrong (the list is not sorted), yet the indicator is still visible from the last sort prior to pressing the "load unsorted" button.
I have tried tableView.setIndicatorImage(newImage, in: column) in an attempt to set the indicator to nil or to a 1 pixel image but it does nothing.
I have also tried drawSortIndicator without success.
In order to have the table initially load with unsorted data, I have added a sort for a non-existent column and on the initial load, I sort on that column. This allows me to always show a sorted list - with unsorted actually sorted on column "None".
So, ultimately, I want the table loaded without sorting. I want to allow sorting, and I want to be able to reload as unsorted, thus removing any sort indicator that may be present.
class AppInfoViewController: NSViewController {
@IBOutlet weak var tableView: NSTableView!
var dataDict: [AppInfo] = AppInfoManager.sharedInstance.appInfoArray
var sortOrder = AppInfoManager.ColumnOrder.None
var sortAscending = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableView.delegate = self
tableView.dataSource = self
tableView.target = nil
let descriptor_0 = NSSortDescriptor(key: AppInfoManager.ColumnOrder.Name.rawValue, ascending: true)
let descriptor_1 = NSSortDescriptor(key: AppInfoManager.ColumnOrder.Date.rawValue, ascending: true)
let descriptor_2 = NSSortDescriptor(key: AppInfoManager.ColumnOrder.Size.rawValue, ascending: true)
tableView.tableColumns[0].sortDescriptorPrototype = descriptor_0
tableView.tableColumns[1].sortDescriptorPrototype = descriptor_1
tableView.tableColumns[2].sortDescriptorPrototype = descriptor_2
}
override func viewWillAppear() {
super.viewWillAppear()
loadSortedData()
}
@IBAction func reloadUnsortedData(_ sender: Any) {
dataDict = AppInfoManager.sharedInstance.appInfoArray
sortOrder = AppInfoManager.ColumnOrder.None
sortAscending = false
let column = tableView.tableColumns[0]
//tableView.setIndicatorImage(nil, in: column)
//tableView.headerView?.needsDisplay = true
//tableView.headerView?.display()
column.headerCell.drawSortIndicator(withFrame: column.headerCell.sortIndicatorRect(forBounds: (tableView.headerView?.frame)!), in: column.tableView!, ascending: false, priority: 1)
tableView.reloadData()
}
func loadSortedData() {
dataDict = AppInfoManager.sharedInstance.contentsOrderedBy(sortOrder, ascending: sortAscending)
tableView.reloadData()
}
}
In AppInfoManager class, the sort is accomplished like follows:
class AppInfoManager {
static let sharedInstance: AppInfoManager = AppInfoManager()
var appInfoArray:[AppInfo] = [AppInfo]()
public enum ColumnOrder: String {
case None
case Name
case Date
case Size
}
func contentsOrderedBy(_ orderedBy: ColumnOrder, ascending: Bool) -> [AppInfo] {
let sortedFiles: [AppInfo]
switch orderedBy {
case .Name:
if ascending == true {
sortedFiles = appInfoArray.sorted(by: {$0.appTitle < $1.appTitle })
} else {
sortedFiles = appInfoArray.sorted(by: {$0.appTitle > $1.appTitle })
}
case .Date:
if ascending == true {
sortedFiles = appInfoArray.sorted(by: {$0.pid < $1.pid })
} else {
sortedFiles = appInfoArray.sorted(by: {$0.pid > $1.pid })
}
case .Size:
if ascending == true {
sortedFiles = appInfoArray.sorted(by: {$0.executableName < $1.executableName })
} else {
sortedFiles = appInfoArray.sorted(by: {$0.executableName > $1.executableName })
}
case .None:
sortedFiles = appInfoArray
}
return sortedFiles
}
}
In AppInfoViewController (NSTableViewDataSource)
extension AppInfoViewController: NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return dataDict.count
}
func tableView(_ tableView: NSTableView, sortDescriptorsDidChange oldDescriptors: [NSSortDescriptor]) {
guard let sortDescriptor = tableView.sortDescriptors.first else {
return
}
if let order = AppInfoManager.ColumnOrder(rawValue: sortDescriptor.key!) {
sortOrder = order
sortAscending = sortDescriptor.ascending
loadSortedData()
}
}
}
To remove sorting from the table, set a variable equal to an empty array of NSSortDescriptors, then set the table's sortDescriptors to the empty array and call reloadData().
class AppInfoViewController: NSViewController {
let defaultSortDescriptors = [NSSortDescriptor]()
}
@IBAction func reloadUnsortedData(_ sender: Any) {
tableView.sortDescriptors = defaultSortDescriptors
tableView.reloadData()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With