我想根据要显示的数据动态隐藏/显示 NSTableView 中的某些列 - 基本上,如果一列为空,我希望隐藏该列。我目前正在使用控制器类作为表的委托填充表。
有任何想法吗?我看到我可以在 Interface Builder 中设置隐藏的列,但是似乎不是检查这些列并检查它们是否为空的好时机,因为似乎没有一种方法是在填充表中的所有数据之前/之后调用。
在 Mac OS X v10.5 及更高版本中,有NSTableColumn的setHidden:
选择器。
这允许使用标识符动态隐藏/显示列:
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];
当然,您也可以添加格式化程序和所有这些东西。
它在界面生成器中不起作用。但是它以编程方式工作。下面是我如何将带有标识符“Status”的 NSTableViewColumn 绑定到我的 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];
我目前没有完整的答案,但请查看 Bindings。使用 Cocoa Bindings 通常可以做各种各样的事情。
NSTableColumn 没有可见性绑定,但您可以将宽度设置为 0。
然后你可以将它绑定到 Null 占位符,并将这个值设置为 0 - 但不要忘记将其他占位符设置为合理的值。
(正如我所说,这只是一个开始,可能需要一些调整)。
没有一次填充所有数据。NSTableView 不存储数据,它动态地从其数据源(或绑定到对象,如果您使用绑定)中请求它。它只是使用从数据源获取的数据进行绘制并将其丢弃。例如,您不应该看到表格要求任何不可见的数据。
听起来您正在使用数据源?当数据发生变化时,你有责任在表上调用 -reloadData,这有点用词不当。这更像是“使一切无效”。
也就是说,您应该已经知道数据何时更改。这就是您可以计算应该隐藏哪些列的点。
@amrox - 如果我正确理解您的建议,您是说我应该将值绑定到表中 NSTableColumns 的隐藏属性?这似乎可行,但是我认为 NSTableColumn 没有隐藏属性,因为 isHidden 和 setHidden 消息控制列的可见性 - 这告诉我这不是属性,除非我错过了一些东西(这是很有可能的)。
NSTable 只是绘制表格的类。正如您自己所说,您有一些类将表作为委托,并且该类为表提供要显示的数据。如果您将表数据作为 NSArray 存储在您的委托类中,那么应该很容易找出一列是否为空,不是吗?并且 NSArray 通过委托方法询问您的类有多少列,所以当您被问到时,为什么不查找您有多少列数据并报告该数字而不是您在内部存储的实际列数,然后在被要求时提供(列,行)的数据,只需跳过空列。
我想使用 Cocoa 绑定和实际isHidden
标志发布我为 Swift 4 更新的解决方案,而不触及列宽(因为之后您可能需要恢复原始值......)。假设我们有一个复选框来切换某些列的可见性(或者您可以随时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 上那样在 Interface Builder 中绑定标志:您可以看到Enabled
orEditable
绑定,但只有通过编程才能访问isHidden
列的标志,因为它在 Swift 中被调用。
如评论中所述,第二种方法依赖于您必须在选择相关列后通过 Identity 字段上的 Interface Builder 手动设置的列标识符,或者,如果您有一个列名数组,您可以枚举表列并分配标识符以及绑定,而不是重复类似的代码行。
我找到了一个简单的解决方案。
如果要使用 Cocoa 绑定技术隐藏任何列:
NSArrayController,
创建一个属性/参数/槽/键值,NSNumber
如果您希望隐藏特定列,则该值为 0,否则为任何值。maxWidth
参数绑定到数据槽,如(1)中所述。我们将使用maxWidth
绑定参数作为消息接收者。import Cocoa
class Column: NSTableColumn {
/// Observe the binding messages
override func setValue(_ value: Any?, forKey key: String) {
if key == "maxWidth" && value != nil { // Filters the signal
let w = value as! NSNumber // Explores change
if w == NSNumber(integerLiteral: 0) {
self.isHidden = true
} else {
self.isHidden = false
}
return // No propagation for the value change
}
super.setValue(value, forKey: key) // Propagate the signal
}
}
Column.