How to draw on top of an image in Apple WatchKit

Suppose you’re writing a simple game for Apple Watch – for example, you might have a treasure map image and you want to render a cross on it in a random position to locate the treasure.
This is tricky, because WatchKit severely limits your options for laying out UI primitives on the screen. For example, if you put a label and an image onto a StoryBoard, it will tile them (rather than letting you put one on top of the other).

The approach I’ve adopted is:

  • Create a Group in the story board and set its background image
  • Add an image view within the Group
  • Create a context and use CoreGraphics to write into it
  • Apply the context to the image view

Set up a new iOS WatchKit App, then drag a Group and Image from the Object Library onto the storyboard:
TreasureMap StoryBoard

In the WatchKit App assets, create a new image set and drag your background image onto the x2 outline:
TreasureMap ImageSet

Set the background image on the group:
TreasureMap SetBackground

Then create an outlet in the InterfaceController for the image – one way is to control-drag from the outline view of the storyboard into the interface controller’s swift file. I called mine OverlayImage to convey the purpose.

Finally, add the code that will leverage the CoreGraphics library to draw into the overlay – the work is done in drawCross() which is called from awakeWithContext(). I’ve split out line and circle drawing methods for clarity.

class InterfaceController: WKInterfaceController {
    // Create by control-dragging to the StoryBoard
    @IBOutlet var OverlayImage: WKInterfaceImage!
    let imageWidth : CGFloat = 312.0
    let imageHeight : CGFloat = 348.0 // 390 - 42 for status bar on 42mm watch
    override func awakeWithContext(context: AnyObject?) {

    override func willActivate() { ... } // standard
    override func didDeactivate() { ... } // standard
    func drawCross()
        // Begin image context and grab context
        let context = createContext()
        // Draw our primitives
        drawLine( context, startX: 75, startY: 150, endX: 125, endY: 200 )
        drawLine( context, startX: 75, startY: 200, endX: 125, endY: 150 )
        drawCircle( context, radius : 10, centreX : 100, centreY : 175 )
        // End by applying our graphics to the Overlay image
        applyContextToImage( context )
    func createContext() -> CGContext?
        // The 'opaque' parameter is false, so that we overlay 
        // rather than the static image underneath
        UIGraphicsBeginImageContextWithOptions( CGSizeMake( imageWidth, imageHeight ), false, 0 )
        let context = UIGraphicsGetCurrentContext()
        CGContextBeginPath( context )
        return context
    func drawLine( context : CGContext?, startX : CGFloat, startY : CGFloat, endX : CGFloat, endY : CGFloat )
        CGContextSetStrokeColorWithColor( context, UIColor.blackColor().CGColor )
        CGContextSetLineWidth(context, 3.0)
        CGContextMoveToPoint( context, startX, startY )
        CGContextAddLineToPoint( context, endX, endY )
        CGContextStrokePath( context )
    func drawCircle( context : CGContext?, radius : CGFloat, centreX : CGFloat, centreY : CGFloat )
        let diameter = radius * 2.0
        let rect = CGRect( x: centreX - radius, y : centreY - radius, width : diameter, height : diameter )
        CGContextSetLineWidth( context, 3.0 )
        CGContextSetStrokeColorWithColor( context, UIColor.blackColor().CGColor )
        CGContextStrokeEllipseInRect( context, rect )
    func applyContextToImage( context : CGContext? )
        let img = UIGraphicsGetImageFromCurrentImageContext()
        OverlayImage.setImage( img )

All being well, you can now run your WatchKit App and check that the black cross and circle have been drawn on top of the background image!

TreasureMap WatchApp


Filed under Programming, Swift

3 responses to “How to draw on top of an image in Apple WatchKit

  1. Pingback: How to write a Watch Face App for Apple Watch | musingstudio

  2. Pingback: How to draw text onto an image in Apple Watch App | musingstudio

  3. Pingback: How to switch watch faces using swipe gestures | musingstudio

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s