I searched far and wide for tips on this and didn’t come across any, so here’s the best guide to this I can muster.
Basic rules of the game are as follows:
- If you create the columns in Cocoa, do not autorelease or release them; leave that extra retain count. If you create the columns in Interface Builder, give them an extra retain before you start doing anything with them. This prevents them from disappearing on you as you add/remove them.
- Life is easier if you have a direct way of getting to the columns. This can be one ivar per column or one collection ivar holding them all (NSArray, NSDictionary, or NSSet).
- Either way, you want to do this after the NIB has loaded and before the window is up. I add my code into windowControllerDidLoadNib: but it’s entirely possible awakeFromNib will work as well.
- Do not mess with retain counts after you ensure you’re in the hole for one. It’s a perfect balance. The sole exception is during dealloc of your view/document and then you finish them off with the rest of your ivars and give up your claim.
So let’s start a program and remove unwanted columns. Presume that NSTableView aTableView has an NSTableColumn aColumn. This can be something you made in code or linked in IB; it doesn’t matter.
[aColumn retain];if (![[NSUserDefaults standardUserDefaults] boolForKey:@“showColumn”]) [aTableView removeTableColumn:aColumn];
Easy. Then in your dealloc method, just give aColumn a release and let Cocoa even the score as the NIB is closed out.
Now, you can get more complicated if you like and store the identifiers for the table columns in a preference array and then loop over those identifiers, calling tableColumnWithIdentifier: to get the column object and remove it, that works as well and gives you room for expansion (just add identifiers).
Later, when you want to add/remove, you’ll want to think up a menu system you like. You’ll probably want to make a function that generates a column menu because you’ll be using it in two places: the menu bar and the table header. You can use either internal constants and the menu item’s tag or representedObject with the table column itself. Doesn’t matter. It only matters that when whatever method you have setup to toggle the columns is called it knows which column to add or remove. I’ll go the representedObject route here.
- (void) toggleColumns: (id) sender
{
NSTableColumn *col = [sender representedObject];
if([aTableView tableColumnWithIdentifier:[col identifier]])
[aTableView removeTableColumn:col];
else
[aTableView addTableColumn:col];
[aTableView sizeToFit];
}
So all we’re doing here is asking the table if col exists in it. If so, remove it. If not, add it. Then after the change is done, we tell the table view to resize the columns so that they’re all visible. Voila.
Now I mentioned that you’d want a function to return a menu earlier, and for a reason. While you can maintain a menu in the menubar because the menubar is retaining it, you’re going to have a fun time doing the same thing twice: once in the menu bar and once on the table’s contextual menu (because you need one). So whip up that function that makes the menu as you like it and then set the menu like so:
[[aTableView headerView] setMenu:[self columnMenu]];
That sets the contextual menu for the table column headers so that a right-click lets you quickly toggle those columns.
It’s easy stuff, but I just hadn’t seen someone put something like this together and some of this was a little odd to me. Have fun with it, and I hope you let me customize my columns everywhere!

Check out http://www.cocoabuilder.com/archive/message/cocoa/2003/11/16/77603
I used the info in it for the basis of my NSTableView subclass. It acts similar to what you have for hiding/showing a column but adds a couple more items that you’ll need to cover in your version. Mainly the saving and restoring of column size, position, and visibility. You just have to add in hooks to save the info to prefs and restore from them at load.
One thing to note if you use it, don’t use NSTableView’s autosave feature. They don’t play well together. When I had it on, columns would disappear until the app’s prefs were deleted if they were hidden at quit. You might be able to override NSTableView to use the column state methods when it does the autosave. I haven’t had a chance to look into it, so I don’t know for sure. I should probably look into it before I start up my new project.
This is exceptionally helpful. Thanks for taking the time to put it online.