swiftuiviewsubclasscgpointuigraphicscontext

change color from CGPoint line in a subclass of uiview


My code is trying to change the color of the line from red to blue when the func dizzy in class View Controller is called. The problem is I dont know how to do it from class view controller. I can do it in class Canvas but I need to control it from func dizzy becuase it serves as a button in class viewController.I don't care if I have to create a func in canvas func and then call it from viewController.

class ViewController: UIViewController {
    var canvas = Canvas()
@objc func dizzy() {

}}



    class Canvas: UIView {

// public function
func undo() {
    _ = lines.popLast()
    setNeedsDisplay()
}

func clear() {
    lines.removeAll()
    setNeedsDisplay()
}




var lines = [[CGPoint]]()

override func draw(_ rect: CGRect) {
    super.draw(rect)

    guard let context = UIGraphicsGetCurrentContext() else { return }

    context.setStrokeColor(UIColor.red.cgColor)
    context.setLineWidth(5)
    context.setLineCap(.butt)

    lines.forEach { (line) in
        for (i, p) in line.enumerated() {
            if i == 0 {
                context.move(to: p)
            } else {
                context.addLine(to: p)
            }
        }
    }

    context.strokePath()

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    lines.append([CGPoint]())
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let point = touches.first?.location(in: self) else { return }
    guard var lastLine = lines.popLast() else { return }
    lastLine.append(point)
    lines.append(lastLine)
    setNeedsDisplay()
}

}

Solution

  • Add a property called strokeColor to your Canvas:

    class Canvas : UIView {
        var strokeColor = UIColor.red {
            didSet {
                self.setNeedsDisplay()
            }
        }
    
        ... 
    }
    

    Use strokeColor in draw(rect:):

    context.setStrokeColor(strokeColor.cgColor)
    

    Then in dizzy() set the canvas' strokeColor to .blue:

    class ViewController: UIViewController {
        var canvas = Canvas()
    
        @objc func dizzy() {
            canvas.strokeColor = .blue
        }
    }
    

    Any time you set the strokeColor of the Canvas, it will trigger a redraw by calling self.setNeedsDisplay() in its didSet property observer. The new call to draw(rect:) will use the new color to redraw the view.