Xcode & broad system font weight
Since starting working with Swift and Apple frameworks I often find myself dealing with epic issues, most relate to features that are not come across every day and not explicit bugs, just things that were not well thought through. Hopefully this will be a series of unique and useful solutions, not pure bitching, with today’s post-mortem on BroadSystemFontWeight warning and broken fonts.
Things go wrong when compiling storyboards that contain text with default system font and custom weight using OS X 10.11 SDK and deployment targets below that.
Xcode, oh boy…
Behind the scenes Xcode creates NSFont instance with selected configuration and sets it onto particular text field — works great with San Francisco in El Capitan, but apparently Xcode has forgotten font weights of Helvetica Neue, default system font in Yosemite. Frankly, it remembered about them not that long ago and everything was good — this is especially ironic with Apple’s love for great typography.
In theory and in practice Xcode has everything it needs to handle this automatically, which would be the ideal solution. Less ideally there would be a way to manually specify fallback fonts in Interface Builder, I believe this is already possible for iOS targets.
Less-less ideally it would be nice to use custom inspectable property on extended NSTextField instance to set font weight, do necessary checks behind the scenes, set the right font with the right weight, make use of live rendering and everything would look neat inside IB and inside the app, but… Live rendering of directly extended controls works only for iOS targets, for everything else Xcode is way more limited — it always renders the base control added from object library while custom views don’t show any inherited attributes.
Many use Interface Builder, many don’t — it’s a preference, the most reasonable argument is that time it helps to save is nothing compared to time wasted resolving problems that it brings. True, the amount of time I spent figuring out all dos and don’ts of live rendering is pretty tremendous. In defence, things get better with every Xcode update, live rendering and auto layout are already amazing enough, while certain pleasures still have to be compromised, hopefully soon this won’t be the case any longer.
Less-less ideal solution
The final solution is similar to one described above — using inspectable preferredFontWeight property to explicitly specify what it should be in OS X 10.10. As said, there’s one drawback — interface builder doesn’t provide the very much desired live rendering when using regular system font with custom preferredFontWeight property, so, font weights for 10.11 and 10.10 must be configured separately with above average chances of setting different values and messing things up.
Lastly, open up identity inspector and set custom class to TextField, preferred font weight attribute now must be visible in attribute inspector, set the required value, build and enjoy the result.
If you want to do that for every textfield, you can try doing this the extension way, which won’t require changing class in identity inspector — for that replace @IBDesignable public class TextField: NSTextField with extension NSTextField.
Yes, one more thing
The BroadSystemFontWeight warning won’t go away, Xcode will continue to do it every time storyboard gets compiled — the trick is to set storyboard target to a higher value.
Be warned, this may break logic that Xcode adds specifically for lower targets, I didn’t come across any issues, but I assume it’s possible, in which case you’ll have to live with the warning.
Almost forgot, the warning shown by Xcode is well… fucking useless to say the least. If you have huge storyboard with numerous textfields that you want to review and update, you can go into report navigator, find compile storyboard message and open raw log using the menu button on the right.
Entries under /* com.apple.ibtool.document.warnings */ header will contain storyboard element ids similar to IM7-vE-4BZ, knowing which you can open your storyboard in text editor, search for that id and either find more information about the element from its content or modify it right there if you’re comfortable doing that.