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練習帳