2015-07-06 7 views
7

Sto provando a visualizzare un grafico di linea/passaggio su Apple Watch utilizzando watchOS 2. A differenza di iOS 9, watchOS 2 non supporta Quartz. Supporta solo Core Graphics. Ho provato a scrivere del codice per disegnare un grafico a linee, ma sto ricevendo un errore "CGContextRestoreGState: contesto 0x0 non valido .Questo è un errore grave.Questa applicazione, o una libreria che utilizza, sta usando un contesto non valido e sta quindi contribuendo a un degrado della stabilità e dell'affidabilità del sistema Questo avviso è una cortesia: si prega di risolvere questo problema, che diventerà un errore fatale in un prossimo aggiornamento. "Rendering di un grafico a linee su Apple Watch utilizzando watchOS 2

Di seguito è riportato il pezzo di codice che ho usato:

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() 
    } 
} 

mio risultato finale dovrebbe essere qualcosa di simile Azioni app presenti su Apple Watch. Quando l'utente fa clic su azioni specifiche, sarà in grado di visualizzare/visualizzare le statistiche di quel titolo. Qualcuno può aiutarmi per ottenere questo.

+0

Mi dispiace, non so circa la vostra domanda. Ma hai provato a definire un ImageSequence con le immagini di un grafico a linee? Questo ti darà l'opportunità di usarlo in un WKInterfacePicker e utilizzare la corona digitale. – Philip

+1

grazie :) philip –

risposta

11

sono riuscito a rendere le linee con i seguenti passi:

  • Creare un contesto grafico bitmap-based e rende il contesto corrente utilizzando UIGraphicsBeginImageContext.
  • Disegna nel contesto.
  • Estrarre CGImageRef dal contesto e convertirlo in oggetto UIImage.
  • Mostra l'immagine su WKInterfaceGroup o WKInterfaceImage.

Codice:

// 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 è di proprietà WKInterfaceImage. Per me funziona.

Inoltre posso disegnare utilizzando UIBezierPath su watchos come segue:

// 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) 

È possibile controllare i codici di esempio here.

+0

Non dimenticare la retina su Apple Watch! Per generare il contesto ratina utilizzare UIGraphicsBeginImageContextWithOptions (size, false, 2.0) con uiimage = UIImage (cgImage: cgimage, scale: 2.0, orientation: .up) – icompot

0

Il contesto qui non è CGContext, quindi hai il problema. Non penso che tu possa utilizzare Core Graphics direttamente su Apple Watch.

2

Ecco il codice 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) 
+0

Una volta forzato a scartare il contesto, lo si utilizzerà in modo condizionale ... come chiudere le operazioni dell'intero contesto in una chiusura "if let context = context" e usare il contesto senza ricomprare nulla ... – konran

0

Grafico render è fatto con l'aiuto di bezierPath e che viene convertito in immagine da attaccato alla Apple Osservare

// Swift-3 Xcode-8.1

importazione UIKit classe InterfaceController: WKInterfaceController {

@IBOutlet var graphImage: WKInterfaceImage! 
override func awake(withContext context: Any?) { 
    super.awake(withContext: context) 

    // Configure interface objects here. 
} 
override func willActivate() { 

    super.willActivate() 
    let path = createBeizePath() 

    //Change graph to image 
    let image:UIImage = UIImage.shapeImageWithBezierPath(bezierPath: path, fillColor: .red, strokeColor: .black) 
    graphImage.setImage(uiimage) 
} 

//Draw graph here 
func createBeizePath() -> UIBezierPath 
{ 
    let path = UIBezierPath() 
    //Rectangle path Trace 
    path.move(to: CGPoint(x: 20, y: 100)) 
    path.addLine(to: CGPoint(x: 50 , y: 100)) 
    path.addLine(to: CGPoint(x: 50, y: 150)) 
    path.addLine(to: CGPoint(x: 20, y: 150)) 
    return path 
    } 
} 

extension UIImage { 
     class func shapeImageWithBezierPath(bezierPath: UIBezierPath, fillColor: UIColor?, strokeColor: UIColor?, strokeWidth: CGFloat = 0.0) -> UIImage! { 
      bezierPath.apply(CGAffineTransform(translationX: -bezierPath.bounds.origin.x, y: -bezierPath.bounds.origin.y)) 
      let size = CGSize(width: 100 , height: 100) 
      UIGraphicsBeginImageContext(size) 
      let context = UIGraphicsGetCurrentContext() 
      var image = UIImage() 
      if let context = context { 
       context.saveGState() 
       context.addPath(bezierPath.cgPath) 
       if strokeColor != nil { 
        strokeColor!.setStroke() 
        context.setLineWidth(strokeWidth) 
       } else { UIColor.clear.setStroke() } 
       fillColor?.setFill() 
       context.drawPath(using: .fillStroke) 
       image = UIGraphicsGetImageFromCurrentImageContext()! 
       context.restoreGState() 
       UIGraphicsEndImageContext() 
      } 
      return image 
     } 
    }