1

I'm sure there's a simple answer to this, but I'm pretty noob to programming and have searched extensively here and on the few Undo tutorials I could find.

I have two buttons and a UITextField with a number in it. The buttons increment the number in the textfield up or down by 1 respectively. I have several more sets of these two buttons and a textfield, each representing something different. Then I have undo and redo buttons that undo the changes to the text fields caused by pressing the buttons. This all works great.

So now I'm trying to add the ability to undo changes from editing the text field directly with the number pad, so that it goes into the same undo stack and can be undone and redone from the same undo and redo buttons.

Here's a snippet of the code that controls the undo and redo of the button presses. Then, like I said, I have several more sets of these that all go into the same undo stack. Thanks.

The UITextField

@IBOutlet weak var Money: UITextField!

The Undo and Redo Buttons

@IBAction func Undo(_ sender: UIButton)
{
    undoManager?.undo()
}
@IBAction func Redo(_ sender: UIButton)
{
    undoManager?.redo()
}

The Up One and Down One Buttons

@IBAction func MonDown(_ sender: UIButton)
{
    subtractOneMon(Mon: Money)
}

@IBAction func MonUp(_ sender: UIButton)
{  
    addOneMon(Mon: Money)
}

The Functions Registering the Undo/Redo

func subtractOneMon(Mon: UITextField)
{
    undoManager?.registerUndo(withTarget: self, handler:
    {(targetSelf) in
        targetSelf.addOneMon(Mon: self.Money)
    })

    let Mon = Double(Money.text!)
    let NewMon = Double(Mon! - 1)
    Money.text = Int(NewMon).description
}
func addOneMon(Mon: UITextField)
{
    undoManager?.registerUndo(withTarget: self, handler:
    {(targetSelf) in
        targetSelf.subtractOneMon(Mon: self.Money)
    })

    let Mon = Double(Money.text!) ?? 0
    let NewMon = Double(Mon + 1)
    Money.text = Int(NewMon).description
}
LWT
  • 11
  • 1

1 Answers1

0

You might want to add an "Editing Changed" IBAction for your text field. This function will be called each time any content of the field is changed.

You'd want to store the previous value of the text field somewhere. Inside the "Editing Changed" IBAction you'd register an undo operation in your undoManager using the previous value and then update the previous value with the current value.

P.S. There's a potential memory leak in the way your handlers are implemented: currently they are holding a strong reference to your UIViewController. Consider adding [weak self] in the capture list. Check out the Memory Management article by John Sundell to learn more.

Vadim Belyaev
  • 2,456
  • 2
  • 18
  • 23
  • Thanks Vadim. I have tried using the "Editing Changed" IBAction as well as the "Editing Did Begin" in conjunction with the "Editing Did End" IBActions, which are more appropriate since I don't really care about what happens between editing, just the final edit after tapping done. What I can't seem to figure out is the second part: registering an undo operation using the previous value and the update the previous value with the current value. Could you suggest some code for that? – LWT Feb 03 '20 at 07:23
  • PS. Thanks for catching the memory leak. – LWT Feb 03 '20 at 07:23