核心数据文本资产有一个瞬态属性textStorage
,该属性会持续保存在contents
类型NSData
中。在某些情况下,在编辑textStorage
核心数据后保存上下文不会保存更改。该应用正在使用BSManagedDocument
与父管理对象上下文一起保存在后台。下面是一个伪日志,用于说明正在发生的事情。预计第二个日志将被持久保存,但父上下文将恢复为原始日志。
这是我在TextAsset实现中选择处理编码/解码的方式吗?(见下文)?
编辑前的原始文本存储:
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.
THIS GETS DELETED
Donec ullamcorper nulla non metus auctor fringilla.
子级(主要文档)上下文中willSave:
的文本存储(在文本视图中编辑后):
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.
Donec ullamcorper nulla non metus auctor fringilla.
父级(背景保存)上下文中willSave:
的文本存储(保存子级上下文后):
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.
THIS GETS DELETED
Donec ullamcorper nulla non metus auctor fringilla.
正如你所看到的那样,“删除已删除”行仍在那里。
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"contents"]) {
return [keyPaths setByAddingObject:@"textStorage"];
}
return keyPaths;
}
- (void)setTextStorage:(NSTextStorage *)textStorage {
[self willChangeValueForKey:@"textStorage"];
[self setPrimitiveValue:textStorage forKey:@"textStorage"];
[self didChangeValueForKey:@"textStorage"];
}
- (NSTextStorage *)textStorage
{
[self willAccessValueForKey:@"textStorage"];
NSTextStorage *textStorage = [self primitiveValueForKey:@"textStorage"];
[self didAccessValueForKey:@"textStorage"];
if (textStorage == nil) {
NSData *contents = [self contents];
if (contents != nil) {
textStorage = [NSKeyedUnarchiver unarchiveObjectWithData:contents];
[self setPrimitiveValue:textStorage forKey:@"textStorage"];
}
}
return textStorage;
}
- (void)willSave
{
NSTextStorage *textStorage = self.textStorage;
if (textStorage != nil) {
[self setPrimitiveContents:[NSKeyedArchiver archivedDataWithRootObject:textStorage]];
}
else {
[self setPrimitiveContents:nil];
}
[super willSave];
}
答案 0 :(得分:0)
进一步研究后发现,当子上下文中对象的contents
值在保存时被推送到父对象时,会导致问题。如果父上下文中的托管对象仍在内存中,则它本身仍将在内存中具有瞬态textStorage
。因此,使用上面的代码,它只会再次归档textStorage
,而不是使用更新的contents
。
通过重置textStorage
时(基元)contents
更改,可以避免此行为。