NSUndoManager 灾难

Posted

技术标签:

【中文标题】NSUndoManager 灾难【英文标题】:NSUndoManager Disaster 【发布时间】:2015-03-24 20:30:26 【问题描述】:

我是一个 16 岁的热心程序员,现在我正在开发一个应用程序,一个简单的应用程序,它只有一个按钮,可以将整数加 1 并在标签中显示它,&我'我想添加一个撤消按钮。从我研究过 NSUndoManager 应该会有所帮助。问题是我无法让它工作!这个问题似乎很明显,但我从 youtube 学到了所有我知道的东西,因此不知道很多事情。 这是我的代码:

@implementation ViewController

NSUndoManager *undoManager;

-(IBAction)add1:(id)sender

    Count = Count + 1;

    Counter.text = [NSString stringWithFormat:@"%i", Count];

    [undoManager prepareWithInvocationTarget:self];

    [undoManager registerUndoWithTarget:self selector:@selector(add1:) object:Counter.text];
    [undoManager setActionName:NSLocalizedString(@"actions.update", @"Update Score")];


-(IBAction)Undo:(id)sender

    [undoManager undo];
    Counter.text = [NSString stringWithFormat:@"%i", Count];


- (void)viewDidLoad 

    Count = 0;

    undoManager =[[NSUndoManager alloc]init];

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.

@end

当你回答时,请尽量不要说非常专业的词,或者如果你确实定义了它们,因为正如我之前所说,我不知道很多事情,我可能听不懂你说的话,我真的很想学习这个。我的应用程序的示例代码,但正确编程了 NSUndoManager 会很棒,所以我可以比较它并找出我的错误是什么。

谢谢!

【问题讨论】:

解释撤消时实际发生的情况,以及如何触发撤消 在分配/初始化undoManager 之后,尝试将undoManager 的三行代码从add1 方法放入viewDidLoad 生命周期方法中。这有帮助吗? 我该怎么做?也许示例代码会有所帮助。 您的问题解决了吗?需要更多信息? 我真的没有:/我想对它进行编程,以便当我点击撤消按钮而不是运行我编写的基本上撤消的方法时,它只记得它上次做了什么并且撤消它:P 我在答案中被告知的是,我需要编写一个方法来执行我在调用撤消时想要发生的事情,但这与仅声明一个执行撤消的 IBAction 方法相同,并且NSUndoManager 没用,你明白我需要什么吗? 【参考方案1】:

您需要一个与-add1: 方法相反的方法。然后,您需要将其设置为撤消操作的选择器:

- (IBAction) add1:(id)sender

    Count = Count + 1;
    Counter.text = [NSString stringWithFormat:@"%i", Count];

    [undoManager registerUndoWithTarget:self selector:@selector(subtract1:) object:sender];
    [undoManager setActionName:NSLocalizedString(@"Increment Score", @"Name for undo action")];


- (IBAction) subtract1:(id)sender

    Count = Count - 1;
    Counter.text = [NSString stringWithFormat:@"%i", Count];

    [undoManager registerUndoWithTarget:self selector:@selector(add1:) object:sender];
    [undoManager setActionName:NSLocalizedString(@"Decrement Score", @"Name for undo action")];

因此,撤消-add1: 的方法是调用-subtract1:,撤消-subtract1: 的方法是调用-add1:。此外,由于-subtract1: 注册了一个撤消操作,这意味着您可以获得重做功能。 (在撤消过程中注册的撤消操作被理解为如果用户选择重做他们撤消的操作,则重做操作。)

注意:当你使用-registerUndoWithTarget:... 时,你不要使用-prepareWithInvocationTarget:。您可以使用其中一个。

此外,您的-Undo: 方法不需要设置Counter.text,因为这应该由撤消操作自动完成。

【讨论】:

那么,如果我做一个获取棒球比赛统计数据的大型应用程序,例如,我将不得不编写整个代码但倒退?或者有没有办法管理整个程序,以便注册更改,然后程序只是将整个事情重置为最近一次更改发生之前的状态? 我不认为它是倒写任何东西。在任何典型的程序中,无论如何您都将提供这两种操作。您还可以以更通用的方式编写代码,例如有一个将给定值添加到计数的方法,不一定是 1。然后您可以使用 1 调用它来进行增量操作,它会注册一个调用自身的撤消操作除了否定的值。 (也就是说,-add1: 方法的简化示例过于简单,因此不切实际。更现实的代码不需要这种笨拙的方法来执行撤消操作。)

以上是关于NSUndoManager 灾难的主要内容,如果未能解决你的问题,请参考以下文章

NSUndoManager 检测核心数据实体的实际删除

Xcode LLDB 打印语句失败 - NSUndoManager

UITextView 和 NSUndoManager 同步

一一保存 NSUndoManager 事务

如何使用 CoreData 为某些操作/实体禁用 NSUndoManager?

取消编辑:NSUndoManager 或单独的 NSManagedObjectContext 进行编辑?