Smug logo small@2x

Coding for high resolution on OS X? Read this.

• Chris Liscio

I don't ever want to see this in your layer-backed and/or layer-hosting view's code:

someLayer.contentsScale = [[NSScreen mainScreen] backingScaleFactor];

Because it makes the following assumptions:

Chances are you picked that bad habit up from iOS programming, because it seems to be a common idiom.

If you're writing a layer-backed or layer-hosting view on OSX, please implement the following NSView method:

- (void)viewDidChangeBackingProperties;

And, it should look something like this:

- (void)viewDidChangeBackingProperties {
    self.layer.contentsScale = [[self window] backingScaleFactor];
    self.someOtherLayer.contentsScale = self.layer.contentsScale;
    self.yetAnotherLayer.contentsScale = self.layer.contentsScale;
    // and so on...
}

Lucky for you, NSWindow maintains its backingScaleFactor based on the screen that it is currently drawn by, and you will get the appropriate call to viewDidChangeBackingProperties when the window moves between two screens with varying contentsScale values.

Special case for custom CALayer subclasses

If you have to deal with custom CALayers that host a collection of sublayers, you need to ensure that your CALayer is the delegate for its sublayers, and you can add the following method implementation:

- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow *)window {
    return YES;
}

Of course, there are cases where you might not want to return YES all the time, and you should be sure to update your layer's contents image here, if required (As @rudyrichter pointed out). I'm sure you're smart enough to figure out what to do in your particular application…

Recommendations

I learned the above after some trial-and-error, and then spending some time reading this document. I suggest you do the same.

You should also be working with an external display attached to your Retina-enabled Mac (I use the Thunderbolt Display) if you're serious about implementing support for high resolution displays on OS X properly. There are a lot of tricky situations you can get into with two displays, and I think it's important to handle them well.