KVO与NSUndoManager

时间:2014-03-09 22:12:03

标签: cocoa key-value-observing

我的文档类中有一个名为passDescription的属性,类型为NSMutableDictionary。当我致电setPassDescription:时,使用NSData将该属性的当前值存档到NSJSONSerialization实例中。该属性的支持ivar passDescription已更新,然后注册撤消操作。操作调用的选择器会重新组合NSData,并调用setPassDescription:

现在,这是小丑:使用键值观察观察passDescription。在Xcode的调试器中进行了大量的实验和检查,发现旧值和新值相同。 (我知道这不是一个指针别名问题,因为这就是我使用NSData实例的原因。在记录新值之前创建NSData,使其独立于它因此,当我按下Command-Z进行撤消时,没有任何反应,因为刚刚恢复的值与撤消时覆盖的值没有区别。

我能想到的唯一可能导致这种情况的原因是KVO在调用passDescription之前为我设置setPassDescription: ivar。为什么会这样,我怎么能阻止KVO这样做呢? (我已经确认setter没有被调用两次。如果是,我会在调试器控制台中看到双输出。)

以下是setPassDescription:的来源。

- (void)setPassDescription:(NSDictionary *)param
{
    NSLog(@"passDescription (before) = \n%@", passDescription);

    NSError *error;
    NSData *archivedOldValue = [NSJSONSerialization dataWithJSONObject:passDescription options:0 error:&error];
    NSAssert(archivedOldValue != nil, @"Could not archive old pass description: %@", error);

    NSData *blob = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:&error];

    if (blob == nil) @throw [NSException exceptionWithName:@"PBJSONException" reason:@"Could not serialize pass.json" userInfo:@{ @"error": error }];

    [self.fileBrowserRoot fileWrapperWithName:@"pass.json"].fileContents = blob;

    [passDescriptionLock lock];
    [[self.undoManager prepareWithInvocationTarget:self] setPassDescriptionFromData:archivedOldValue];
    passDescription = param;
    [passDescriptionLock unlock];

    NSLog(@"passDescription (after) = \n%@", passDescription);

    // After the pass description has been set, refresh the list of build issues.
    [self recheckForIssues];
}

0 个答案:

没有答案