After manually adding a PKStroke, the UndoManager no longer works

If you have a PKCanvasView and call

canvasView.drawing.strokes.append(myNewStroke), it renders the UndoManager unusable, or at least makes it start fresh.

The undo buttons in the PKToolPicker will reflect what seems like an accurate number of undos (ie if I have 5 strokes I can tap undo 5 times before it's grayed out), but those undo presses won't actually do anything.

This presents an issue in our project as we're trying to remove a PKStroke if it looks like a circle and insert a new perfect circle, but when we do this we can't press undo to get rid of it.

Trying to hack together my own solution with .registerUndo causes a lot of issues also. I would be able to undo the things I'd specifically registered, but could no longer undo the rest of the strokes.
I'm seeing similar behaviour whenever I procedurally modify the PKDrawing of a PKCanvasView. Specifially when doing:
  • canvasView.drawing.strokes[i].mask = newMask

  • canvasView.drawing.strokes[i] = newStroke

  • canvasView.drawing.remove(at:i)

  • canvasView.drawing.insert(stroke, at:i)

the undoManager (or its stack of undo operations) gets messed up and stops working. I assume this is a bug in iOS 14 beta? Hopefully the PencilKit team will fix this before the release of iOS 14?
I've filed a radar for this (FB7794075), but I've discovered a workaround in the mean time:

Code Block
self.undoManager?.groupsByEvent = false
self.drawing.strokes.append(YOURCUSTOMPKSTROKE)
for (index, _) in self.drawing.strokes.enumerated() {
    self.undoManager?.beginUndoGrouping()
    self.undoManager?.registerUndo(withTarget: self, handler: {
        $0.drawing.strokes.remove(at: index)
    })
    self.undoManager?.endUndoGrouping()
}
self.undoManager?.groupsByEvent = true

@WillBishop Thanks for finding a solution to this problem. I just wanted to add the "Redo" method in case everyone else need it:


self.undoManager?.groupsByEvent = false
self.drawing.strokes.append(YOURCUSTOMPKSTROKE)
for (index, _) in self.drawing.strokes.enumerated() {
    self.undoManager?.beginUndoGrouping()
    self.undoManager?.registerUndo(withTarget: self, handler: {
        $0.drawing.strokes.remove(at: index)
        self.undoManager?.registerUndo(withTarget: self, handler: { // redo here
            $0.drawing.strokes.append(YOURCUSTOMPKSTROKE)
        })
    })
    self.undoManager?.endUndoGrouping()
}
self.undoManager?.groupsByEvent = true
After manually adding a PKStroke, the UndoManager no longer works
 
 
Q