[swift unboxed]

Safely unboxing the Swift language & standard library


Notes and playground on using the CustomPlaygroundQuickLookable protocol.

10 November 2015 ∙ Protocols ∙ written by

CustomPlaygroundQuickLookable, as the name suggests, allows you to provide a custom quick look for your types.

It’s a simple protocol with one required method:

public func customPlaygroundQuickLook() -> PlaygroundQuickLook

That leads to the question, what the heck is a PlaygroundQuickLook?

As with many great things in Swift, it’s an enumeration! There are enum cases for different kinds of supported quick looks, from plain text to attributed string to bezier path. Each case has an associated value to hold the instance of the correct type: String, Bool, NSBezierPath, etc.

That means all you need to do in your customPlaygroundQuickLook() implementation is initialize and return the correct enum value.

For plain text, this is pretty simple:

struct Employee: CustomPlaygroundQuickLookable  {
  var name: String
  var department: String

  func customPlaygroundQuickLook() -> PlaygroundQuickLook {
    return .Text("Employee named \(name) in the \(department) department")

Things are just as simple for Float and Int and such. For the more complicated types, you may need to do some more work.

In Practice

I’ve coded up some examples into a playground; feel free to download it, check out the code, and play around with it yourself: QuickLooks playground.

Implementation Details

You’ll notice many of the associated values are of type Any to be cross-platform and open to interpretation. For example, the Color case takes either a UIColor or NSColor instance depending on the platform. The playground above uses the OS X versions of these objects but you can easily swap in an iOS playground and UIKit objects.

I’ve listed the enumeration cases below, with a note on how well they work. You can also check out the official documentation for the up-to-date list.

public enum PlaygroundQuickLook {
  // primitive types: these work as expected!
  case Text(String)
  case Int(Int64)
  case UInt(UInt64)
  case Float(Float32)
  case Double(Float64)
  case Logical(Bool)

  // fancy types: these also work as expected!
  case Image(Any)
  case Color(Any)
  case AttributedString(Any)
  case View(Any)
  case URL(String)

  // geometry and shapes: work as expected!
  case BezierPath(Any)
  case Rectangle(Float64, Float64, Float64, Float64)
  case Point(Float64, Float64)
  case Size(Float64, Float64)

  // these don't render properly :(
  case Range(UInt64, UInt64)

  // couldn't get these to work :(
  case Sound(Any)
  case Sprite(Any)

If you figure out how to get the Sound or Sprite cases working, please let me know!