0

Core Data 文本资产有一个临时属性textStorage,该属性被持久保存在contentstypeNSData中。在某些情况下,在编辑textStorageCore Data 后保存上下文不会保存更改。该应用程序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.

如您所见,“此已删除”行仍在其中。

TextAsset.m 实现的相关部分

+ (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];
}
4

1 回答 1

0

contents进一步研究后发现,当子上下文中的对象的值在保存时被推送到父级时,就会导致问题。如果父上下文中的托管对象仍在内存中,则它本身仍将在内存中具有瞬态textStorage。因此,使用上面的代码,它只会textStorage再次存档,而不是使用更新的contents.

通过重置textStoragewhen (primitive) contentschanges 可以避免这种行为。

于 2013-08-25T16:00:23.887 回答