我的文档类中有一个名为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];
}