【问题标题】:Does NSUndoManager retain objects?NSUndoManager 是否保留对象?
【发布时间】:2010-11-23 03:12:01
【问题描述】:

我执行以下操作:

    Path2D *pathToRemove = [path copy];
    [[[self undoManager] prepareWithInvocationTarget:self] removePath:pathToRemove atIndex:index];
[pathToRemove autorelease];

我还有一个清除按钮:

[undoManager removeAllActions];

问题是 removeAllActions 使应用程序崩溃。当我删除 [pathToRemove autorelease] 时,它起作用了(或者至少没有崩溃。它仍然可能是内存泄漏)。我想我假设 undoManager 在“prepareWithInvocationTarget”调用中传递时保留了“pathToRemove”。

不是这样吗?如果不是这种情况,则可能会发生崩溃,因为对“removeAllActions”的调用正在释放“PathToRemove”对象。但这意味着它是 NSUndoManager 中的一个错误,这种可能性极小。

我可以说我的 copyWithZone 实现也不太可能是罪魁祸首,因为 '[pathToRemove description]' 和 '[path description]' 的 NSLog 输出按预期显示不同的地址。

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 好的,我想通了。 'prepareWithInvokationTarget' 确实保留了它的论点。我的问题是我的 copyWithZone 方法确实不正确。我有一个没有被复制而只保留的对象。因此,当“RemoveAllActions”释放对象并进入各自的 Dealloc 方法时,未“复制”的此成员变量的释放创建了双重释放场景,从而导致崩溃。再次感谢!

标签: nsundomanager


【解决方案1】:

根据文档,prepareWithInvocationTarget: 方法不保留传递给它的参数。从NSUndoManager 文档来看,它似乎只是捕获了NSInvocation,然后再重放它。 NSInvocationobjects 不会在参数中保留对象,除非特别要求这样做。

这并不能完全解释崩溃,因为removeAllActions 只是应该清除撤消堆栈而不对对象执行任何操作。

希望这有助于一些人追查崩溃的根源。

【讨论】:

  • 谢谢。我将尝试使用:registerUndoWithTarget:selector:object。根据文档,这保留了对象,所以我应该能够在调用此注册方法后释放它。
  • 不正确,prepareWithInvocationTarget 确实保留了它的所有参数,但保留了它的目标。
【解决方案2】:

根据我的经验,这不是发布/保留问题。您必须在撤消/重做操作后清除堆栈。为此,您可以为 NSUndoManagerDidUndoChangeNotification 通知注册您的 viewController:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearUndoRedoStack) name:NSUndoManagerDidUndoChangeNotification object:nil];

然后清栈到指定方法上:

- (void)clearUndoRedoStack {
    [undoManager removeAllActions];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    相关资源
    最近更新 更多