I wonder how to memoize stroke in swift

33 Views Asked by At

I recently ventured into utilizing Swift's UIKit to create a custom PencilKit.

My approach involves sampling information about points every time the pencil touches the screen, storing this data in a format like

strokeCollection = {strokes: [Stroke], drawingStroke: Stroke?}

and overriding the UIView's draw method to redraw the view each time the strokeCollection is updated. However, as more strokes are drawn, the app begins to significantly slow down due to the need to redraw every stroke continually.

In React Native Skia, I've used the "createPicture" method to leverage the "Picture" component, keeping previously drawn strokes intact and preventing the app from slowing down. I'm curious if there's a similar technique available in Swift or if you might have other suggestions to address this issue.

My original code draws for every stroke every time as below.

    override func draw(_ rect: CGRect) {
            UIColor.clear.set()
            UIRectFill(rect)
            
            // saved strokes
            if let strokeCollection = strokeCollection {
                if strokeToDraw != nil {
                    for stroke in strokeCollection.strokes {
                        draw(stroke: stroke, in: rect)
                    }
                }
            }
            
            // currently drawing stroke
            if let stroke = strokeToDraw {
                draw(stroke: stroke, in: rect)
            }
        }

func draw(stroke: Stroke, in rect: CGRect) {
        guard stroke.samples.isEmpty == false else { return }
        
        let path = UIBezierPath()
        var previousSample: StrokeSample?
        
        for sample in stroke.samples {
            if let prev = previousSample {
                let midPoint = midpoint(first: prev.location, second: sample.location)
                
                path.addQuadCurve(to: midPoint, controlPoint: prev.location)
            } else {
                path.move(to: sample.location)
            }
            previousSample = sample
        }
        
        if let lastSample = previousSample {
            path.addLine(to: lastSample.location)
        }
        
        if let context = UIGraphicsGetCurrentContext() {
            switch stroke.type {
            case .pen, .marker:
                context.setBlendMode(.normal)
                context.addPath(path.cgPath)
                context.setStrokeColor(stroke.color.cgColor)
                context.setLineWidth(stroke.width * 2)
                context.setAlpha(stroke.opacity)
                context.setLineCap(.round)
                context.setLineJoin(.round)
                context.strokePath()
            case .eraser:
                context.setBlendMode(.clear)
                context.addPath(path.cgPath)
                context.setStrokeColor(stroke.color.cgColor)
                context.setLineWidth(stroke.width * 2)
                context.setAlpha(stroke.opacity)
                context.setLineCap(.round)
                context.setLineJoin(.round)
                context.strokePath()
            }
        }
    }
0

There are 0 best solutions below