Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render a line graph on Apple Watch using watchOS 2

I am trying to render a line/step graph on Apple Watch using watchOS 2. Unlike iOS 9, watchOS 2 doesn't support Quartz. It only supports Core Graphics. I tried writing some code to draw a line graph but I am getting an error "CGContextRestoreGState: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update."

Following is the piece of code I used:

import WatchKit
import Foundation
import UIKit

class InterfaceController: WKInterfaceController{
    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)
        let path = UIBezierPath()
        let startPoint =  CGPointMake(0.0, 0.0)
        path.moveToPoint(startPoint)
        let nextPoint = CGPointMake(20.0, 20.0)
        path.addLineToPoint(nextPoint)
        path.lineWidth = 1.0
        UIColor.whiteColor().setStroke()
        path.stroke()
    }

    override func willActivate() {
        super.willActivate()

    }

    override func didDeactivate() {
        super.didDeactivate()
    }
}

My end result should be something like Stocks app present on Apple Watch. Wwhenever user clicks on particular stock, he will be able to view/visualize the statistics of that stock. Can anybody please help me in achieving this.

like image 239
deepthi toopran Avatar asked Jul 06 '15 22:07

deepthi toopran


People also ask

Can you get line on Apple Watch?

With LINE for Apple Watch, now you can view your messages on your wrist whenever you want. You can even view images! The app even includes a feature that lets you respond to messages with stickers.

How do I use Apple Watch app on Xcode?

In Xcode, choose File > New > Project. Select the watchOS tab. To create a watch-only app, select “App” and click Next. To create a watchOS app bundled with an iOS app, select “iOS App with Watch App” and click Next.

Why won't my control center come up on my Apple Watch?

Open Control Center: From the watch face, swipe up. From other screens, touch and hold the bottom of the screen, then swipe up. Note: You can't open Control Center from the Home Screen on your Apple Watch. Instead, press the Digital Crown to go to the watch face or open an app, then open Control Center.

Is Apple Watch Series 3?

The Apple Watch Series 3 was announced by Apple in September of 2017 alongside the iPhone 8 and iPhone X. It's powered by the dual-core Apple S3 processor and was the first Apple Watch to featured cellular connectivity. When it first introduced, prices for the Apple Watch Series 3 started at $369.


2 Answers

I succeeded to render lines with following steps:

  • Create a bitmap-based graphics context and makes it the current context using UIGraphicsBeginImageContext.
  • Draw into the context.
  • Extract CGImageRef from the context and convert it to UIImage object.
  • Show the image on WKInterfaceGroup or WKInterfaceImage.

Code:

// Create a graphics context
let size = CGSizeMake(100, 100)
UIGraphicsBeginImageContext(size)
let context = UIGraphicsGetCurrentContext()

// Setup for the path appearance
CGContextSetStrokeColorWithColor(context, UIColor.whiteColor().CGColor)
CGContextSetLineWidth(context, 4.0)

// Draw lines
CGContextBeginPath (context);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, 100, 100);
CGContextMoveToPoint(context, 0, 100);
CGContextAddLineToPoint(context, 100, 0);
CGContextStrokePath(context);

// Convert to UIImage
let cgimage = CGBitmapContextCreateImage(context);
let uiimage = UIImage(CGImage: cgimage!)

// End the graphics context
UIGraphicsEndImageContext()

// Show on WKInterfaceImage
image.setImage(uiimage)

image is WKInterfaceImage property. It works for me.

Also I can draw using UIBezierPath on watchOS as follow:

// Create a graphics context
let size = CGSizeMake(100, 100)
UIGraphicsBeginImageContext(size)
let context = UIGraphicsGetCurrentContext()
UIGraphicsPushContext(context!)

// Setup for the path appearance
UIColor.greenColor().setStroke()
UIColor.whiteColor().setFill()

// Draw an oval
let rect = CGRectMake(2, 2, 96, 96)
let path = UIBezierPath(ovalInRect: rect)
path.lineWidth = 4.0
path.fill()
path.stroke()

// Convert to UIImage
let cgimage = CGBitmapContextCreateImage(context);
let uiimage = UIImage(CGImage: cgimage!)

// End the graphics context
UIGraphicsPopContext()
UIGraphicsEndImageContext()

image.setImage(uiimage)

You can check the sample codes here.

like image 119
shu223 Avatar answered Nov 09 '22 05:11

shu223


Here's code in watchOS 3

  // Create a graphics context
        let size = CGSize(width:self.contentFrame.size.width, height:100)


        UIGraphicsBeginImageContext(size)
        let context = UIGraphicsGetCurrentContext()

        // Setup for the path appearance
        context!.setStrokeColor(UIColor.white.cgColor)
        context!.setLineWidth(4.0)

        // Draw lines
        context!.beginPath ();

        context?.move(to: CGPoint())
        context?.addLine(to: CGPoint(x: 100, y: 100))
        context?.addLine(to: CGPoint(x: 0, y: 100))
        context?.addLine(to: CGPoint(x: 100, y: 0))

        context!.strokePath();

        // Convert to UIImage
        let cgimage = context!.makeImage();
        let uiimage = UIImage(cgImage: cgimage!)

        // End the graphics context
        UIGraphicsEndImageContext()

        self.graphGroup.setBackgroundImage(uiimage)
like image 37
Jad Avatar answered Nov 09 '22 06:11

Jad