iospencilkit

PKCanvasView / PKDrawing get strokes selected by lasso


When using PKCanvasView with standard drawing tools (PKToolPicker), there is a lasso tool available. It is possible to select existing pencil strokes and modify them. On the other hand, through PKDrawing it is possible to access all strokes programatically, and process them as needed.

My question is - is it possible to programatically determine which strokes are currently selected by lasso tool? I want to programatically apply some modifications only to selected strokes, not to everything.


Solution

  • I managed to get the lasso selection in a convoluted way. Seems to work well on large drawings and does the job I needed it to do. PencilKit updates very much required though.

    Here's what I did:

    1. Made a copy of the [PKStroke] in a PKDrawing
    2. Deleted the selected PKStrokes from the drawing
    3. Compared the copy and the drawing without selected strokes to get stroke indices

    Code:

     func getLassoSelection() -> ([Int],[Int]) {
        // Assuming the lasso tool has made a selection at this point
        
        // Make a backup of the current PKCanvasView drawing state
        let currentDrawingStrokes = canvasView.drawing.strokes
        
        // Issue a delete command so the selected strokes are deleted
        UIApplication.shared.sendAction(#selector(delete), to: nil, from: self, for: nil)
        
        // Store the drawing with the selected strokes removed
        let unselectedStrokes = canvasView.drawing.strokes
        
        // Put the original strokes back in the PKCanvasView
        canvasView.drawing.strokes = currentDrawingStrokes
        
        // Get the indices of selected strokes using sequenceContainsStroke
        var selectedIndices: [Int] = []
        var unselectedIndices: [Int] = []
        for i in 0...currentDrawingStrokes.count-1 {
            if(unselectedStrokes.contains(strokes[i])) {
                unselectedIndices.append(i)
                continue
            }
            selectedIndices.append(i)
        }
        return (selectedIndices, unselectedIndices)
    }
    
    // Compares the reference of two PKStroke to determine equality
    // PKStroke needs to conform to Equatable for PKStroke.contains to work in previous function
    extension PKStroke: Equatable {
        public static func ==(lhs: PKStroke, rhs: PKStroke) -> Bool {
            return (lhs as PKStrokeReference) === (rhs as PKStrokeReference)
        }
    }