Half-Assed

Every Mac developer that uses iCloud has a dirty little secret:

They don’t fully test their software before they ship it to customers on the Mac App Store. It’s because Apple won’t let them.

iOS developers, on the other hand, can upload a build to TestFlight and use the app with the iCloud production servers to make sure everything is working great before it gets sent to the App Store for review.

TestFlight has been available to internal developers since iOS 8 was announced in 2014. The system was opened up to external testers who have an iTunes account in the early part of 2015.

Mac developers have never had access to TestFlight, either internally or externally. It’s “coming soon”, and until that day comes, there’s no way to test apps that use the iCloud servers. Which sucks for both the developer and the customer.

But wait, there’s more.

Apple is touting analytics as an awesome new feature for developers that use the App Store to distribute their creations. It’s a huge benefit to our businesses, but only when you’re selling solely on iOS. This feature is nowhere to be found on the Mac App Store. Again, it’s “coming soon”.

Just yesterday, Apple did something great for developers. They now block reviews on beta OS releases. Unless that operating system is for the Mac.

Let me guess: it’s “coming soon”.

It doesn’t take a genius to see that Apple is doing something it rarely does: a half-assed job.

As developers, we completely understand how much work it is to announce these kinds of initiatives and get them working on multiple platforms. It’s not easy and takes a lot of resources. But it’s clear that these precious resources are not being allocated.

Apple needs to change its priorities for the Mac App Store or just shut the whole thing down. As it now stands, developers who are tired of being second-class citizens are making that decision for them and leaving on their own.

This is a pity because the Mac App Store is a great way for customers to download and purchase software. No one benefits from this half-assed job.

Updated July 23rd, 2015: I think the thing that bothers me most about this situation is the inequality. Mac developers aren’t getting the same value from the App Store as their counterparts on iOS. We all pay Apple 30% of our earnings to reach our customers, we should all get the same functionality for that fee.

Dupe this Radar if you agree.

I Left My System Fonts in San Francisco

Note: This post contains out-of-date information and is left here as a historical record. Please refer to this new post on using system fonts in CSS. Thanks!

Apple is working on a lovely new system font for both iOS and OS X. We first saw the San Francisco font on the Apple Watch: we’ll soon be seeing it on all of Apple’s devices.

As a developer, there are often cases where we need to use the system font on web pages. Many times these pages are embedded in our apps and manage things like remote settings or documentation. In these contexts, matching the content to what the customer sees in their surrounding environment makes a big impact on the user experience. Think about how out of place an app feels when it displays Sparkle release notes in Lucida Grande while running on Yosemite.

We’ll soon be faced with a lot of surrounding content that’s displayed in San Francisco and will need ways to specify that same font in our CSS. It turns out that’s not a simple thing to do.

Traditionally, we’ve specified fonts explicitly. Something like this could be used to get San Francisco:

body {
  font-family: "San Francisco", "Helvetica Neue", "Lucida Grande";
}

Unfortunately, on a fresh install of OS X 10.11 (El Capitan) there’s no San Francisco font installed:

All Fonts on El Capitan

But it’s the system font, so how is this possible?

Apple has started abstracting the idea of a system font: it doesn’t have a publicly exposed name. They’ve also stated that any private names are subject to change. These private names all begin with a period: the Ultralight face for San Francisco is named “.SFNSDisplay-Ultralight”. To determine this name, you need to dig around in the font instances returned by NSFont or UIFont; it’s not easy by design.

The motivation for this abstraction is so the operating system can make better choices on which face to use at a given weight. Apple is also working on font features, such as selectable “6” and “9” glyphs or non-monospaced numbers. It’s my guess that they’d like to bring these features to the web, as well.

As a part of this abstraction, there’s now a new generic family name: -apple-system. The markup looks like this:

body {
  font-family: -apple-system, "Helvetica Neue", "Lucida Grande";
}

Unfortunately, it’s very poorly documented. Most of the information I’ve found about this name comes from the WebKit source code. It certainly feels like work-in-progress.

Another disappointment is that this generic family name only works in Safari. Of course you wouldn’t expect Google to support an “-apple” prefix, but the WebKit source also shows a -webkit-system-font. Since the latest version of Chrome is based on a fork of WebKit, it’s not surprising that it’s ignored by Blink.

Adding to the confusion, Safari on iOS has added system font styles that match the Dynamic Type feature. These keywords can be used on iOS 7 and later:

-apple-system-headline1
-apple-system-headline2
-apple-system-body
-apple-system-subheadline1
-apple-system-subheadline2
-apple-system-footnote
-apple-system-caption1
-apple-system-caption2
-apple-system-short-headline1
-apple-system-short-headline2
-apple-system-short-body
-apple-system-short-subheadline1
-apple-system-short-subheadline2
-apple-system-short-footnote
-apple-system-short-caption1
-apple-system-tall-body

Since OS X doesn’t have a way to adjust type dynamically, these keywords are unavailable on the desktop (source). Of course, there’s no support in Chrome either.

Also note that these keywords won’t work in your font-family definitions; they only work when used with font. If you’d like to learn more about this functionality, these tutorials by the ChocolateScript developers and Thomas Fuchs are very helpful.

If you’re a designer or developer who works on Apple devices, chances are good that you’ve installed the San Francisco font manually. Don’t get fooled like I did: most of the folks that visit your site won’t have these fonts installed. Also, Apple’s license for San Francisco limits redistribution, so it can’t be used as a web font. (And you agreed to this license before downloading the font.)

So what’s a coder to do?

If you know that your content will only appear in an Apple browser or web view, the markup is pretty simple:

body {
  font-family: -apple-system, "Helvetica Neue", "Lucida Grande";
}

You’ll get the system font on the most current browsers and a fallback to Helvetica Neue or Lucida Grande on older systems.

If Chrome or another browser is a part of the picture, I’d suggest the following:

body {
  font-family: system, -apple-system,
      ".SFNSDisplay-Regular", "Helvetica Neue", "Lucida Grande";
}

The “.SFNSDisplay-Regular” is the private font name for the regular face of San Francisco in the current beta release (remember, it can change at any time!)

Chrome now supports a BlinkMacSystemFont so the private font name is no longer needed:

body {
  font-family: system, -apple-system, BlinkMacSystemFont,
      "Helvetica Neue", "Lucida Grande";
}

For more information about this change in Chrome, see the links at the end of this post.

The “system” generic family name doesn’t currently exist, but I’d encourage browser manufacturers to adopt this technique. It would be helpful for coders on all platforms. On Android, Roboto or Noto could be selected as needed. On operating systems like Windows, where the user can choose their system font, the automatic selection would make content fit in more easily.

Before closing, I’d like to point out the HTML and CSS I used for doing this research. If you’re not running El Capitan yet, this is is how that markup looks in Safari:

Test Page shown in Safari running on El Capitan

And the same page rendered in Chrome:

Test Page shown in Chrome running on El Capitan

The purple line of sample text displays correctly on both browsers using the “hybrid” hack I’ve shown above. That text will also display in Helvetica Neue on Yosemite (10.10) and Lucida Grande on Mavericks (10.9).

As Apple starts to roll out the new software releases that feature San Francisco, I hope the information presented here will be of help. Enjoy!

Updated July 12th, 2015: After some discussion with folks on the WebKit team, the preferred generic font name is “-apple-system”, not “-apple-system-font”; I’ve updated the post accordingly. Also, as I suspected, this change is very much a work in progress and the team is aware that there needs to be more documentation. They also reminded me that Chrome is now based on the Blink fork of WebKit, so I’ve clarified that as well.

Updated July 14th, 2015: Some folks have suggested using “sans-serif” to get the system font on El Capitan. My testing shows that all browsers on all versions of OS X render this generic font name in Helvetica (not Helvetica Neue.) Also many browsers give users ways to override this default font. I also updated the sample code so that it works better with Firefox.

Updated July 27th, 2015: Apple’s Surfin’ Safari blog has more information on the new “-apple-system” CSS value for font-family. It also looks like they’re working with the W3C to standardize a “system” generic font family.

Updated January 20th, 2016: Chrome now supports a BlinkMacSystemFont generic font name that behaves like Safari’s -apple-system. Marcin Wichary does a great job of explaining how to use it. As a bonus, he shows how to get the system fonts on other platforms, including Android and Linux.

Bug Writing Season

It’s that time of year: Apple has just released a bunch of amazing new things and we start poking at them. And of course, we encounter things that don’t work like we’d want or expect.

Apple’s engineers like to remind us that there’s a good way to handle that situation. You’ll also see a lot of bug report numbers pass by on the Twitter and Facebook feeds as your colleagues ask for duplicates. We’ll all be spending a lot of time writing Radars.

Now’s the perfect time to start using QuickRadar. As its name suggests, this project run by Amy Worrall, makes creating or duplicating bug reports much quicker. You’ll also find that a native Mac user interface is much easier to deal with than some web form pretending to be iOS 6.

The QuickRadar icon can be shown in your dock or in the menu bar. When you click on the icon or use the global hot key, you’ll be presented with the following UI:

QuickRadar_UI

Note: Since Apple doesn’t provide an API for Radar, the app works by scraping web pages. You’ll need to enter your Apple ID and password in Preferences before you can submit a bug report (and you have the source, so you know exactly how those credentials are being stored and used—it’s all done securely.)

Just fill in the fields and hit Submit. If you have your own internal bug tracker or want to document a workaround, you’ll probably want to copy the Radar number to the clipboard. Sending the bug to Open Radar is awesome if you want to let other developers know about the issue and/or get some duplicate bug reports.

If you want to duplicate a Radar, all you need is the bug report number. For example, say you want to complain about the new developer website being a huge pain in the ass. Just select File a Duplicate… from the QuickRadar menu and you’ll be presented with:

FileDuplicate_UI

After entering the bug number, the user interface will be pre-populated with the information from Open Radar along with a header saying “This is a duplicate of rdar://21372721”. Click Submit and you’re done.

We all know that writing bugs takes time away from doing more interesting things, but it’s still our best way to affect change from within Apple. With these tips, you’ll be able to get back to coding as soon as possible!

An @import-ant Change in Xcode

How many times have you done something like this?

(lldb) p self.window.bounds
error: property 'bounds' not found on object of type 'UIWindow *'
error: 1 errors parsing expression

Followed by a quietly whispered “crap” and some more typing:

(lldb) p (CGRect)[self.window bounds]
(CGRect) $0 = (origin = (x = 0, y = 0), size = (width = 375, height = 667))

And even if you remember to do it when debugging views, you’ll forget in some of the more arcane situations:

(lldb) p CGPointFromString(@"{10.0, 20.0}")
error: 'CGPointFromString' has unknown return type; cast the call to its declared return type
error: 1 errors parsing expression
(lldb) p (CGPoint)CGPointFromString(@"{10.0, 20.0}")
(CGPoint) $1 = (x = 10, y = 20)

Buried deep within the Xcode 6.3 release notes there is a true gem that can relieve this daily frustration.

LLDB’s parser for Objective-C can now go through any module used in your app and determine the types used for all functions and methods it defines. If you’re using UIKit in your app, you can do this:

(lldb) expr @import UIKit

Which will save a lot of subsequent typing:

(lldb) p self.window.bounds
(CGRect) $4 = (origin = (x = 0, y = 0), size = (width = 375, height = 667))
(lldb) p CGPointFromString(@"{10.0, 20.0}")
(CGPoint) $5 = (x = 10, y = 20)

Note that the app must be linked against the module being used in the @import. For example, if you try to use that command in a Mac app, you’ll get:

(lldb) expr @import UIKit
error: Header search couldn't locate module UIKit
error: 1 errors parsing expression

And if you’re a forgetful developer like I am, you can save yourself some more typing by adding this to ~/.lldbinit:

command alias uikit expr @import UIKit
command alias foundation expr @import Foundation

For those of us that work on both Mac and iOS projects, it’s just a matter of typing “uikit” or “foundation” at the beginning of a debugging session:

(lldb) uikit
(lldb) p self.window.bounds
(CGRect) $4 = (origin = (x = 0, y = 0), size = (width = 375, height = 667))

Note that you’ll need to use the “uikit” alias every time you start a new debugging session: the @import is not maintained across build and run cycles. Similarly, if you add something to .lldbinit, it won’t be read until the next time start debugging. Also, as much as we’d all love to automatically do the @import in the LLDB initialization file without typing “uikit”, that’s not currently possible (probably because this file is loaded before any modules are known by the debugger.)

Updated: Steve Streza came up with a brilliant hack: add the “uikit” alias as a breakpoint in the application delegate and set it to auto-continue.

Thanks to Oliver Letterer for the tweet that inspired this post and Peter Steinberger for bringing it to my attention with a retweet. This little trick is going to save us all a lot of time and frustration!