NSUndoManager分组操作撤销重做后动作名称显示异常问题咨询
问题原因
你遇到的菜单项名称混乱问题,根源在于joinRegions内部调用的removeRegions和addRegions会各自设置独立的撤销动作名称。这些子方法的动作名称会覆盖你为joinRegions撤销分组设置的"Join Regions",尤其是在撤销再重做的流程中,子方法的动作名称会被优先显示,导致标签与实际操作不符,但执行逻辑本身是正确的。
修复方案
核心思路是让removeRegions和addRegions在被joinRegions调用时不设置自身的动作名称,避免干扰分组的统一名称。具体修改如下:
1. 修改addRegions方法
新增带参数的重载方法,控制是否设置动作名称,保留原方法兼容现有调用:
- (void)addRegions:(NSArray *)regions shouldSetActionName:(BOOL)shouldSetActionName { [[self.undoManager prepareWithInvocationTarget:self] removeRegions:regions shouldSetActionName:shouldSetActionName]; // ... <实际添加区域的代码> ... if (shouldSetActionName && ![self.undoManager isUndoing]) { [self.undoManager setActionName:@"Add Region(s)"]; } } - (void)addRegions:(NSArray *)regions { [self addRegions:regions shouldSetActionName:YES]; }
2. 修改removeRegions方法
同样添加重载方法,控制动作名称的设置:
- (void)removeRegions:(NSArray *)regions shouldSetActionName:(BOOL)shouldSetActionName { [[self.undoManager prepareWithInvocationTarget:self] addRegions:regions shouldSetActionName:shouldSetActionName]; // ... <实际删除区域的代码> ... if (shouldSetActionName && ![self.undoManager isUndoing]) { [self.undoManager setActionName:@"Remove Region(s)"]; } } - (void)removeRegions:(NSArray *)regions { [self removeRegions:regions shouldSetActionName:YES]; }
3. 修改joinRegions方法
调用子方法时传入NO,禁止子方法设置动作名称,确保分组的统一名称生效:
- (void)joinRegions:(NSArray *)regions { [self.undoManager beginUndoGrouping]; MP3Region *joinedRegion = [[MP3Region alloc] init]; // ... <相应设置合并区域参数的代码> ... [self removeRegions:regions shouldSetActionName:NO]; [self addRegions:@[joinedRegion] shouldSetActionName:NO]; [self.undoManager setActionName:@"Join Regions"]; [self.undoManager endUndoGrouping]; }
修改完成后,joinRegions的撤销分组动作名称会始终保持为"Join Regions",不会被子方法的动作名称覆盖,撤销和重做的菜单项标签就能与实际操作匹配了。
内容的提问来源于stack exchange,提问作者tajmahal
相关产品推荐
相关产品推荐

