Sizing a Preference Pane Dynamically

March 10, 2009

If you’ve tried to develop a system preference pane on the Mac that works across both Tiger and Leopard you may have run into a small but annoying problem: although the System Preferences window is resized to the height of your view it has a fixed width and does not resize your view to fit within that width. This renders any autoresizing rules applied to your view useless, so you end up with a preference pane that is either clipped on 10.4 and earlier or too small on 10.5 and later.

The Apple examples for handling this situation recommend creating two separate views sets: one set for 10.4 and earlier and another set for 10.5 and later. Unless your layout is significantly altered between the two OS versions this has some drawbacks. You now have two sets of views to build and maintain, and if a future version of OS X alters the System Preferences window size again you’re going to need yet another set.

Luckily there is a simple solution. Although System Preferences does not resize the width of our view for us we can do this ourselves quite easily by matching the content width of the System Preferences window.

- (void)mainViewDidLoad {
    NSRect rect = [[self mainView] frame];
    NSWindow *systemPrefsWindow = [[NSApplication sharedApplication] mainWindow];
    rect.size.width = [systemPrefsWindow contentRectForFrameRect:[systemPrefsWindow frame]].size.width;
    [[self mainView] setFrame:rect];

We could simplify this code a bit by using the superview’s frame or the contentView of systemPrefsWindow, but contentRectForFrameRect: is used for a couple of reasons. We need to resize the view before it is first displayed, but the superview will not have valid size information until didSelect, at which point our view is already on the screen. In addition, by obtaining the content rect from the window rather than the frame of the contentView we are making no assumptions about the size of whatever contentView currently represents.

This simple change sizes our main view to the width of the System Preferences window, our autoresizing rules are now applied, and viola: a single set of views that scales to a System Preferences window of any width.