[cocoa][swift]NSUndoManager


NSUndoManagerの利用は、Swiftで楽になったと思うが、その仕組みが見えにくくなったと思うので、Objective-Cの場合から説明する。

CocoaのUndoとRedoは、NSInvocationというクラスでNSObjectの子クラスとメソッドを保持し、それをNSUndoManager内のスタックで管理することで実現している。

なんらかの操作を行うと、Undoに必要なNSInvocationのインスタンスがUndoスタックに積まれていく。

ユーザがUndoを行うと、Redoに必要なNSInvocationのインスタンスがRedoスタックに積まれていく。

Objective-Cのコードで、以下のようになる。

- (void)makeItHotter
{
    temperature = temperature + 10;
    [[undoManager prepareWithInvocationTarget:self] makeItColder];
}
 
- (void)makeItColder
{
    temperature = temperature - 10;
    [[undoManager prepareWithInvocationTarget:self] makeItHotter];
}

makeItHotterで温度を10度上げて、makeItColderをNSUndoManagerに積む。

makeItColderでは、温度を10度下げて、makeItHotterをNSUndoManagerに積む。

これをSwiftを書く場合、積むメソッドのselectorを用意するのが面倒になるのだが、selectorを必要としないメソッドが用意されていた。以下のようになる。

func makeItHotter() {
    var temperature = self.textField.intValue
    temperature = temperature + 10
    self.undoManager?.registerUndo(withTarget: self, handler: {
        vc in
        vc.makeItColder()
    })
    self.textField.intValue = temperature
}
 
func makeItColder() {
    var temperature = self.textField.intValue
    temperature = temperature - 10
    self.undoManager?.registerUndo(withTarget: self, handler: {
        vc in
        vc.makeItHotter()
    })
    self.textField.intValue = temperature
}

ソースコード
GitHubからどうぞ。

https://github.com/murakami/workbook/tree/master/mac/Temperature - GitHub

【関連情報】
Cocoa Programming for Mac OS X

Cocoa.swift

Cocoa勉強会 関東

Cocoa練習帳