NSUndoManager被撤消单撤消mouseDrag期间所做的所有更改

问题描述 投票:1回答:1

我有一个的NSView对象,取入该变化在其各自的视图绘制的对象的位置的mouseDragged事件。在我NSViewController类,它然后检索新的位置和新的价值分配给我的模型数据对象。换句话说,每次调用的mouseDragged事件时,视图控制器更新新的位置。所以,在相同的范围内,所述的ViewController经由NSUndoManager寄存器撤消事件,以允许用户执行撤消操作。

当多个位置更新行动被注册到撤消管理的问题就出现了。当用户执行撤销动作,而不是只有最近的动作越来越从撤消栈中弹出,动作的其余部分也获得撤消。

作为参考,这里是我的代码:

// MyViewController.m
- (void)translateObject:(double)dx
          withYPosition:(double)dy
{
    NSMutableDictionary* transformData = [self.transformData transform];

    double t_x = [[transformData objectForKey:@"translate_x"] doubleValue];
    double t_y = [[transformData objectForKey:@"translate_y"] doubleValue];

    t_x -= x;
    t_y -= y;

    [self translateShape:@[[NSNumber numberWithDouble:t_x],[NSNumberNumberWithDouble:t_y]]];
}

- (void)translateShape:(NSArray*)val
{
    NSMutableDictionary* transformData = [self.transformData transform];

    double old_t_x = [[transformData objectForKey:@"translate_x"] doubleValue];
    double old_t_y = [[transformData objectForKey:@"translate_y"] doubleValue];
    double t_x = [[val objectAtIndex:0] doubleValue];
    double t_y = [[val objectAtIndex:1] doubleValue];

    [transformData setObject:[NSNumber numberWithDouble:t_x] forKey:@"translate_x"];
    [transformData setObject:[NSNumber numberWithDouble:t_y] forKey:@"translate_y"];
    [self.transformData setTransform:transformData];
    [self.glView setNeedsDisplay:YES];

    [[self undoManager] registerUndoWithTarget:self
                                  selector:@selector(translateShape:)
                                    object:@[[NSNumber numberWithDouble:old_t_x],
                                             [NSNumber numberWithDouble:old_t_y]]];

    [[self undoManager] setActionName:@"Shape Drag Move"];  
}

/* * * I have also done this:

- (void)translateShape:(NSArray*)val
{
    NSMutableDictionary* transformData = [self.transformData transform];

    double old_t_x = [[transformData objectForKey:@"translate_x"] doubleValue];
    double old_t_y = [[transformData objectForKey:@"translate_y"] doubleValue];
    double t_x = [[val objectAtIndex:0] doubleValue];
    double t_y = [[val objectAtIndex:1] doubleValue];

    [transformData setObject:[NSNumber numberWithDouble:t_x] forKey:@"translate_x"];
    [transformData setObject:[NSNumber numberWithDouble:t_y] forKey:@"translate_y"];
    [self.transformData setTransform:transformData];
    [self.glView setNeedsDisplay:YES];

    [[self undoManager] registerUndoWithTarget:self
                                  selector:@selector(unTranslateShape:)
                                    object:@[[NSNumber numberWithDouble:old_t_x],
                                             [NSNumber numberWithDouble:old_t_y]]];

    [[self undoManager] setActionName:@"Shape Drag Move"];  
}

- (void)unTranslateShape:(NSArray*)val
{
    NSMutableDictionary* transformData = [self.transformData transform];

    double old_t_x = [[transformData objectForKey:@"translate_x"] doubleValue];
    double old_t_y = [[transformData objectForKey:@"translate_y"] doubleValue];
    double t_x = [[val objectAtIndex:0] doubleValue];
    double t_y = [[val objectAtIndex:1] doubleValue];

    [transformData setObject:[NSNumber numberWithDouble:t_x] forKey:@"translate_x"];
    [transformData setObject:[NSNumber numberWithDouble:t_y] forKey:@"translate_y"];
    [self.transformData setTransform:transformData];
    [self.glView setNeedsDisplay:YES];

    [[self undoManager] registerUndoWithTarget:self
                                  selector:@selector(translateShape:)
                                    object:@[[NSNumber numberWithDouble:old_t_x],
                                             [NSNumber numberWithDouble:old_t_y]]];

    [[self undoManager] setActionName:@"Shape Redo Drag Move"]; 
}

* * */

下面是我期望的撤销发生,对什么我实际观察,质量低劣的图:

enter image description here

任何人都可以阐明了这一点?谢谢。

objective-c cocoa nsundomanager
1个回答
0
投票

由于詹姆斯Bucanek的有关设置NSUndoManager的runLoopModes暗示,我能找出为什么NSUndoManager在过程中鼠标按下,的mouseDragged,和MouseUp事件解开我所有的注册索马里发展事务处的。在我的案件事实证明,NSUndoManager组由事件注册的所有索马里发展事务处(我想这也意味着任何撤消在事件的mouseDragged注册动作)。对于简单地注册在你的NSView子类索马里发展事务处,下面应该工作:

/** Simple case: Everything handled by NSView subclass **/

- (void)mouseDown:(NSEvent *)event
{
    // Set your undo manager's groupsByEvent property to NO here
}

- (void)mouseDragged:(NSEvent *)event
{
    // Tell your undo manager to begin grouping
    // Register undo and redo actions here
    // Tell your undo manager to end grouping
}

- (void)mouseUp:(NSEvent *)event
{
    // Set your undo manager's groupsByEvent property to YES here
}

由于我使用的协议来设置我的模型的属性在我的视图控制器,我简单地实现,上述协议是在我的NSView的鼠标按下/ mouseUp事件事件称为另一种方法随后setGroupsByEvent为NO和YES。如果有人知道一个更好的实施/解决这个问题,随时纠正我。希望这可以帮助!

© www.soinside.com 2019 - 2024. All rights reserved.