Swift: Adding custom quick look to your classes

QuickLook is Apple’s embedded quick preview feature. It was first introduced in OS X Leopard back around 2007 or so. Since that time, the concept has broadened. Implementations now appear in iOS and have been added to the latest version of the Xcode IDE.

In Swift playgrounds, QuickLook provides small eye icons in the execution results gutter to the right of the code you enter. When you see an eye, you can tap on it to view a preview of the result that has been generated.

Although Xcode will QuickLook class components, it doesn’t provide direct, custom approach for the class as a whole. Each element is listed, and any inspections of those elements is passed along to embedded inspectors.

What you get generally looks something like this:

Screen Shot 2014-06-26 at 9.55.01 AM

Even when what you really want is more like this:

Screen Shot 2014-06-26 at 9.58.40 AM

 

Fortunately, Xcode and Swift enable you to build your own QuickLook class previews, albeit with limits. To support QL, your class must derive from NSObject. If you don’t explicitly descend from NSObject, throw an @objc annotation in there to provide compatibility, as in the following example.

@objc class BezierCircle {
    var color : UIColor
    var path : UIBezierPath
    var radius : Double
    init (_ radius : Double, _ color : UIColor = UIColor.redColor())
    {
        path = UIBezierPath(ovalInRect: CGRectMake(0, 0, 2*radius, 2*radius))
        self.radius = radius
        self.color = color
    }

By implementing debugQuickLookObject() in your class, you provide the object that Xcode displays in response to eye-icon clicks. For this Bezier circle example, I built an image using the internal path and color:

func debugQuickLookObject() -> AnyObject? {
    UIGraphicsBeginImageContext(CGSizeMake(radius * 2.0, radius * 2.0))
    color.set(); path.fill()
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image
}

As you see in the above image, the gutter text reflects the returned object, in this case a 100×100 image.  If you want to add more information, draw it into the image. You cannot return a tuple with this approach, and your QL return type must conform to the following classes. If you return a custom class other than these, the QuickLook behavior reverts to the default. If your QL object needs to be a tuple of some sort, consider adding a computed property instead.

enum QuickLookObject {
  case Text(String)
  case Int(Int64)
  case UInt(UInt64)
  case Float(Double)
  case Image(Any)
  case Sound(Any)
  case Color(Any)
  case BezierPath(Any)
  case AttributedString(Any)
  case Rectangle(Double, Double, Double, Double)
  case Point(Double, Double)
  case Size(Double, Double)
  case Logical(Bool)
  case Range(UInt64, UInt64)
  case View(Any)
  case Sprite(Any)
  case URL(String)
  case _Raw(UInt8[], String)
}

 

Comments are closed.