I want to implement a shake to undo on my iPhone App, in Swift.
For now it works, but it didn't display an Alert asking to validate the undo gesture (with buttons "Cancel" and "Undo"). I can add this alert in the right place myself, but I'm not certain I should. Some articles make me think that the alert should appear automatically, in the undo/redo process, so there's something I missed, perhaps...
Here are the relevant bits of code
In the viewController
override func becomeFirstResponder() -> Bool {
return true
}
and
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
snowflake.undoLastAction()
}
}
and in my snowflake class, the action is inserting or modifying point in an array, so I store the value before the change in oldPathPoints, then
// Action du undo
undoManager?.registerUndo(withTarget: self, handler: { (targetSelf) in
snowflake.pathPoints = oldPathPoints
})
and finally the undo method
func undoLastAction() {
undoManager?.undo()
createPath()
}
So,
I succeeded to do it (with the help of a 5-years Book from Matt Neuburg!) So, there's nothing to make in the viewController, I deleted becomeFirstResponder and motionEnded.
All is in the SnowFlake class: I added
let undoer = UndoManager()
override var undoManager : UndoManager? {
return self.undoer
}
override var canBecomeFirstResponder: Bool { return true }
So I communicate the undoManager I use and the class (a view here) can become firstResponder
after the manipulation of the view that can be undone (in my case in touchesEnded
)
, I call
self.becomeFirstResponder()
I deleted the undoLastAction function (useless now), and changed the undo action to a fonction
changePathUndoable(newPathPoints: finalPathPoints)
the function is like that
func changePathUndoable(newPathPoints: [CGPoint]) {
let oldPathPoints = Snowflake.sharedInstance.pathPoints
Snowflake.sharedInstance.pathPoints = newPathPoints
// Action du undo
undoer.setActionName("cutting")
undoer.registerUndo(withTarget: self, handler: { (targetSelf) in
targetSelf.changePathUndoable(newPathPoints: oldPathPoints)
})
Snowflake.sharedInstance.createPath()
self.setNeedsDisplay()
}
I had to create the function changePathUndoable instead of calling undoer.registerUndo directly just for having the redo action to work (I didn't test redo before).
I think that all the steps are necessary to do what I wanted: make the view receive the shake event, displays this dialog and be able to undo/redo the modifications.