Динамическое скрытие столбцов в NSTableView
Вопрос
Я хочу динамически скрывать / показывать некоторые столбцы в NSTableView на основе данных, которые будут отображаться - в принципе, если столбец пуст, я бы хотел, чтобы столбец был скрыт.В настоящее время я заполняю таблицу классом контроллера в качестве делегата для таблицы.
Есть какие-нибудь идеи?Я вижу, что могу установить скрытый столбец в Interface Builder, однако, похоже, сейчас не самое подходящее время просматривать столбцы и проверять, пусты они или нет, поскольку, похоже, не существует метода, который вызывался бы до / после заполнения всех данных в таблице.
Решение
NSTable - это просто класс, который рисует таблицу.Как вы сами сказали, у вас есть какой-то класс, который вы предоставляете таблице в качестве делегата, и этот класс загружает в таблицу данные для отображения.Если вы храните данные таблицы как NSArray в вашем классе делегата, должно быть легко выяснить, пуст ли один столбец, не так ли?И NSArray запрашивает ваш класс через метод делегирования, сколько в нем столбцов, поэтому, когда вас спросят, почему бы не посмотреть, сколько столбцов у вас есть данных, и сообщить это число вместо реального количества столбцов, которые вы храните внутри, а затем, когда вас попросят предоставить данные для (столбца, строки), просто пропустите пустой столбец.
Другие советы
В Mac OS X версии 10.5 и более поздних версиях есть setHidden:
селектор для NSTableColumn.
Это позволяет динамически скрывать / показывать столбцы с использованием идентификаторов:
NSInteger colIdx;
NSTableColumn* col;
colIdx = [myTable columnWithIdentifier:@"columnIdent"];
col = [myTable.tableColumns objectAtIndex:colIdx];
[col setHidden:YES];
Я сделал это с помощью привязок, но настроил их программно, а не через Interface Builder.
Этот псевдо-фрагмент должен дать вам представление об этом:
NSTableColumn *aColumn = [[NSTableColumn alloc] initWithIdentifier:attr];
[aColumn setWidth:DEFAULTCOLWIDTH];
[aColumn setMinWidth:MINCOLWIDTH];
[[aColumn headerCell] setStringValue:columnLabel];
[aColumn bind:@"value"
toObject:arrayController
withKeyPath:keyPath
options:nil];
[tableView addTableColumn:aColumn];
[aColumn release];
Конечно, вы также можете добавить форматеры и все такое прочее.
Это не работает в конструкторе интерфейсов.Однако это работает программно.Вот как я привязываю NSTableViewColumn с идентификатором "Status" к ключу в моем NSUserDefaults:
Быстрый:
tableView.tableColumnWithIdentifier("Status")?.bind("hidden", toObject: NSUserDefaults.standardUserDefaults(), withKeyPath: "TableColumnStatus", options: nil)
Цель-C:
[[self.tableView tableColumnWithIdentifier:@"Status"] bind:@"hidden" toObject:[NSUserDefaults standardUserDefaults] withKeyPath:@"TableColumnStatus" options:nil];
На данный момент у меня нет полного ответа, но посмотрите на Привязки.Как правило, с привязками Cocoa можно делать все, что угодно.
Для NSTableColumn нет привязки к видимости, но вы можете установить ширину равной 0.
Затем вы можете привязать его к заполнителю Null и установить это значение равным 0, но не забудьте установить для других заполнителей разумные значения.
(Как я уже сказал, это только начало, возможно, потребуется некоторая доработка).
Невозможно заполнить все данные за один раз.NSTableView не хранит данные, он динамически запрашивает их из своего источника данных (или привязанных к объектам, если вы используете привязки).Он просто рисует, используя данные, которые получает из источника данных, и отбрасывает их.Вы не должны видеть, как таблица запрашивает данные для чего-либо, что не видно, например.
Похоже, вы используете источник данных?Когда данные изменяются, вы несете ответственность за вызов -reloadData в таблице, что немного неправильно.Это больше похоже на "аннулировать все".
То есть вы уже должны знать, когда изменяются данные.Это точка, в которой вы можете вычислить, какие столбцы должны быть скрыты.
@amrox - Если я правильно понимаю ваше предложение, вы говорите, что я должен привязать значение к скрытому свойству NSTableColumns в моей таблице?Похоже, что это сработало бы, однако я не думаю, что у NSTableColumn есть скрытое свойство, поскольку сообщения isHidden и setHidden контролируют видимость столбца, что говорит мне о том, что это не свойство, если я чего-то не упускаю (что вполне возможно).
Я хотел бы опубликовать свое решение, обновленное для Swift 4, используя привязки Cocoa и фактический isHidden
отметьте, не касаясь ширины столбца (так как впоследствии вам может потребоваться восстановить исходное значение ...).Предположим, у нас есть флажок для переключения видимости некоторого столбца (или вы всегда можете переключить hideColumnsFlag
переменную в приведенном ниже примере любым другим способом, который вам нравится):
class ViewController: NSViewController {
// define the boolean binding variable to hide the columns and use its name as keypath
@objc dynamic var hideColumnsFlag = true
// Referring the column(s)
// Method 1: creating IBOutlet(s) for the column(s): just ctrl-drag each column here to add it
@IBOutlet weak var hideableTableColumn: NSTableColumn!
// add as many column outlets as you need...
// or, if you prefer working with columns' string keypaths
// Method 2: use just the table view IBOutlet and its column identifiers (you **must** anyway set the latter identifiers manually via IB for each column)
@IBOutlet weak var theTableView: NSTableView! // this line could be actually removed if using the first method on this example, but in a real case, you will probably need it anyway.
// MARK: View Controller Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
// Method 1
// referring the columns by using the outlets as such:
hideableTableColumn.bind(.hidden, to: self, withKeyPath: "hideColumnsFlag", options: nil)
// repeat for each column outlet.
// Method 2
// or if you need/prefer to use the column identifiers strings then:
// theTableView.tableColumn(withIdentifier: .init("columnName"))?.bind(.hidden, to: self, withKeyPath: "hideColumnsFlag", options: nil)
// repeat for each column identifier you have set.
// obviously use just one method by commenting/uncommenting one or the other.
}
// MARK: Actions
// this is the checkBox action method, just toggling the boolean variable bound to the columns in the viewDidLoad method.
@IBAction func hideColumnsCheckboxAction(_ sender: NSButton) {
hideColumnsFlag = sender.state == .on
}
}
Как вы, возможно, заметили, пока нет способа привязать Hidden
установите флажок в построителе интерфейса, как в XCode10:вы можете видеть Enabled
или Editable
привязки, но только программно у вас будет доступ к isHidden
установите флажок для столбца, как это называется в Swift.
Как отмечено в комментариях, второй метод основан на идентификаторах столбцов, которые вы должны вручную задать либо через Interface Builder в поле Identity после выбора соответствующих столбцов, либо, если у вас есть массив имен столбцов, вы можете перечислить столбцы таблицы и назначить идентификаторы, а также привязки вместо повторения аналогичных строк кода.