I am doing my own localization, where I pre-parse all window controls after loading a window/view, and translate all specially-marked values, tooltips etc.
If I preset a tooltip for a Table Cell View, though, I cannot figure out how to reach it from the NSTableView object.
Here's the cell view in Xcode's IB:
And the tooltip property of the cell view:
How do I get to that TableCellView in its prototype form when I only have a reference to its TableView object, so that I can alter its tooltip for all rows added later?
There must be a way, because how would a TableView know how to add a row when using a NSArrayController
to manage the table view rows, and my code does not explicitly reference these prototypes at all, which means that the NSArrayController
must have a way to find these cell prototypes – and I want to achieve the same.
I understand that I can add a binding from the header view in the code that loads the view, but I am trying to write a generic method that is only given the root tableview and finds all tooltips inside.
I believe this is not possible with AppKit API.
Here's why I come to that conclusion, so that in case I'm wrong (or even if I'm right), the reasoning is still valuable:
For each NSTableViewRow
and NSTableViewCell
that is being created, the owner
receives an -awakeFromNib:
message. The owner is usually your table view controller -- or whatever is the file's owner of the Nib. (To keep it simple, I assume you have a Nib MyTableViewController.xib
for a view controller of the same name, with the Nib containing one table view in a container.)
This is one strong sign (and cause of bugs :)) that each cell you create (not reuse) is created from the Nib.
This is also discussed in literature. From a source on UIKit, though, but similar constraints apply to AppKit Nibs if you want to design cells in separate nibs:
This nib is expected to have exactly one top-level object, and that top-level object is expected to be a UITableViewCell; that being so, the cell can easily be extracted from the resulting NSArray, as it is the array’s only element. Our nib meets those expectations! Problem solved.
(Matt Neuburg: Programming iOS 6; Designing a cell in a nib})
I found that mind-set to be helpful: that the main view controller Nib is, for all intents and purposes, treated as a Nib for the cell in the future.
It's accessible by the NSUserInterfaceItemIdentifier
if you look at registered Nibs: For AppKit, we have NSTableView.registeredNibsByIdentifier
to inspect, and NSTableView.register(_:forIdentifier:)
to change Nib association per cell.
So if you want to adjust something, your best bet is to override the Nib association there.
Nibs are opaque data blobs and have no public surface API. NSNib
has no API to modify any of its objects.
You can't programmatically set the blueprint of the NSNib
that's being loaded, but you can hook into the process:
You can subclass
NSNib
if you want to extend or specialize nib-loading behavior. For example, you could create a customNSNib
subclass that performs some post-processing on the top-level objects returned from theinstantiateNib...
methods https://developer.apple.com/documentation/appkit/nsnib
So when your NSTableViewCell
is being instantiated, you can replace the tooltip.
That means you need a NSNib
subclass with a possibly static var
tooltip to store the next tooltip value; you can't use the Nib file itself as your storage.
The main customization point for NSView-based table views like you have is NSTableViewDelegate.tableView(_:viewFor:row:)
. This also applies to re-used cells, so you get possibly more consistent behavior no matter whether the cell is newly created before or after the point in time you wanted to modify the tooltip.
Since you can't use the Nib itself as your tooltip data storage but need to put a global variable, a property on the view controller (associated with the table view's lifetime), or static var
on a type like MyCustomNib: NSNib
, you might as well use the view controller property and the NSTableViewDelegate
callback in a lot of cases.