Lento con forza

大学生気分のIT系エンジニアが色々書いてく何か。ブログ名決めました。

SwiftのUndoManagerの使い方

Undoを実装したいと思ったのでSwiftのUndoManagerを軽く調べてみました。

developer.apple.com

このクラスにはregisterUndoはあるのですが、registerRedoが存在しません。これによってundoが実現できるのことはわかるのですが、どのようにredoが実装されているのか気になったので確かめてみることにしました。

実験のために簡単なカウンターのコードを書いています。

まずは純粋にregisterUndoを実装してみました。 undoは正常に実行されていますが、redoが動作していないようです。

これの原因は、undoのregisterを実装しただけで完全に自動的にredoも実装されるわけではなかったことにあります。

動作するコードはこちらです

先程のコードで登録されたundoのコードでは数値をマイナス1するだけでしたが、動作するコードではマイナス1する操作に対するundo操作も登録しています。

manager.registerUndo(withTarget: counter, handler: { counter in
    counter.count -= 1
    print("Decremented by undo")
    // It needs registering for redo
    manager.registerUndo(withTarget: counter, handler: { counter in
        counter.count += 1
    })
})

どうやらregisterUndoしか存在しない理由は、undo操作中に行われたundo(つまりredo)が登録された時に、それを自動的にredoとして扱われるということでした。

undoを実装するだけで自動的にredoが実装されるという魔法でもあるのかと思ったのですが、そんなことはありませんでした。

最終的なコードはこのようになりました。

実装を試した後にドキュメントをちゃんと読み直すとこの挙動が説明されていました。ちゃんとドキュメント読みましょう。

When undoing an action, UndoManager saves the operations you reverted to so that you can call redo() automatically.