Search code examples
nstableviewappkitcocoa-bindings

NSTableView (or NSOutlineView) column hiding through contextual menu : a "no code" solution


I searched SO for the best solution to this question, found several clues, while not fully satisfying IMO. So I post below my no-code solution. The goal is to have, as in Finder or other native applications, a contextual menu on the header bar of a table or outline, allowing to select which columns are visibles.


Solution

    1. In IB storyboard, add all the columns you need into the table view. You may set some of them hidden by default.

    2. Ctrl-drag each column from the IB document outline view to the scene controller code view, in order to automatically create weak IBOutlets for each column. The purpose is to be able to target a given column in bindings.

      __weak IBOutlet NSTableColumn *my_column;
      
    3. Add a menu to the storyboard scene with the same number of item as the columns you plan to hide. You do not have to give title to menu items (see next point).

    4. For each menu item, in the bindings pane, add two bindings :

      • Bind the item title to the column title property through your controller outlet : controller_name.my_column.title. This way the menu item will stay in sync with column title, should the code need to change it.
      • THIS ONE IS KEY : Bind the value of the menu item to the column hidden property : controller_name.my_column.hidden. Add a NSNegateBoolean transformer for the menu tick to be meaningful.
    5. Attach the menu to header menu : ctrl-click on the table header view and make connection from the menu outlet to the menu created in #3.

    That it's. No code beside the IBOutlets added in #2.

    The bindings being two ways, un-ticking a menu item will hide the bound column. Also, if the code hides a column the bound menu item will reflect its state.