Archive for December 8, 2016

Thursday, December 8, 2016

How to Do XCTestCase tearDown Wrong (and Right)

Jon Reid (via Natasha Murashev):

In other words, it builds up the entire set of XCTestCase instances before running a single test. […] setUp and tearDown were invented because the entire collection of test cases is created up front. They provide the hooks to manage object life cycle in tests.

This has two important implications:

  1. Anything automatically created as part of the XCTestCase’s initialization will exist too soon.
  2. Anything not released in the tearDown will continue to exist, even while other tests run.

Think of any object that alters global state, and shudder.

Which is too bad because the Swift code isn’t as clean when everything has to be optional, since it isn’t initialized in init.

Method Dispatch in Swift

Brian King:

Compiled programming languages have three primary methods of dispatch at their disposal: direct dispatch, table dispatch, and message dispatch, which I explain below. Most languages support one or two of these. Java uses table dispatch by default, but you can opt into direct dispatch by using the final keyword. C++ uses direct dispatch by default, but you can opt into table dispatch by adding the virtual keyword. Objective-C always uses message dispatch, but allows developers to fall back to C in order to get the performance gains of direct dispatch. Swift has taken on the noble goal of supporting all three types of dispatch. This works remarkably well, but is a source of confusion to many developers, and is behind a number of gotchas that most Swift developers have encountered.


So, how does Swift dispatch methods? I haven’t found a succinct answer to this question, but here are four aspects that guide how dispatch is selected:

  • Declaration Location
  • Reference Type
  • Specified Behavior
  • Visibility Optimizations


Above, I mentioned that methods defined inside the initial declaration of an NSObject subclass use table dispatch. I find this to be confusing, hard to explain, and in the end, it’s only a marginal performance improvement.

Swift extensions use direct dispatch (less dynamic than in the class declaration), while NSObject extensions use message dispatch (more dynamic than in the class declaration). Then he gives an example where an NSObject override method is not called because it’s in an extension rather than directly in the subclass; the location of the initial declaration matters. Also, you can override NSObject extension methods but not Swift ones. And don’t forget protocols. It’s all rather confusing.

Update (2016-12-10): See also: Ling Wang.

Making Sense of Color Management

A Book Apart:

Get clarity in the tricky endeavor of managing colors from initial design to final product. Learn why colors shift, the science behind the human eye and color profiles, and how to set up your image editor and development environment for consistent color. Craig Hockenberry takes you through every step of color management, with indispensable advice on readying your work and workflows for new technologies.

Update (2016-12-09): Craig Hockenberry:

As a developer, you might be interested in taking a look behind the curtains at the book’s mini-site. You’ll find additional articles, new markup for the web, and sample code for both iOS and macOS. The book provides essential background for these examples, but it will give you a taste of what you’ll be learning.

Update (2017-01-03): See also: John Gruber.

The Slowness of Archive Utility

Rob Griffiths:

Not only is this randomly-resizing dialog box visually annoying, it turns what should be a super-fast process into one that takes a ridiculous amount of time. The end result is that users think they have a slow machine—”it took over 12 seconds to expand 25 tiny little archives!”—when what they really have is a horrendously slow GUI interface to a super fast task.

It took just 0.013 seconds with gzip Terminal.

Update (2016-12-09): Nick Heer:

[…] many archives will take less than a second to expand using the Terminal. Those files should, ideally, be unarchived in place, without opening an additional window.