如何从NSPersistentDocument中的Core Data预加载数据?

时间:2013-05-07 18:19:21

标签: macos cocoa core-data preload nspersistentdocument

我有一个NSPersistentDocument带有给定的核心数据模型等等。

我有一个由本文档创建的文件,假设它是 preload.xml 。它“包含”了几个NSManagedObject s。

我想在所有新文档中加载这些对象,这样当我创建一个新文档时,新文档会自动“拥有”preload.xml中的“living”对象。到目前为止,这就是我所做的:

  • 我在项目中复制了preload.xml

  • initWithType:error:方法(创建新文档时调用的方法)中,使用以下代码:

    NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle]
                                                pathForResource:@"preload"
                                                ofType:@"xml"]];
    NSError* err = nil;
    
    [self readFromURL:preloadURL
               ofType:@"xml"
                error:&err] ;
    

这不起作用,因为当我稍后尝试保存我的文档时,假设myNewDoc.xml,此文件为空,但我的所有新数据都保存到preload.xml

我想知道是否需要创建新的storecontextstoreCoordinator或其他内容。我从来没有处理过这样的对象,因为我总是使用NSPersistentDocument

1 个答案:

答案 0 :(得分:1)

获取保存的对象:

    NSPersistentStoreCoordinator * newPersStoreCoord ;
    newPersStoreCoord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:theDoc.managedObjectModel] ;

    NSString * path = [[NSBundle mainBundle] pathForResource:@"preload"
                                                      ofType:@"xml"];
    NSURL *preloadURL = [NSURL fileURLWithPath:path];



    [newPersStoreCoord addPersistentStoreWithType:NSBinaryStoreType
                                    configuration:nil
                                              URL:preloadURL
                                          options:nil
                                            error:NULL] ;

    NSManagedObjectContext * auxMOC = [[NSManagedObjectContext alloc] init] ;
    [auxMOC setPersistentStoreCoordinator:newPersStoreCoord] ;

将它们复制到您的“生活”MOC

  [self loadPreloadedDataFromTheMOC:auxMOC
                             toTheMOC:theDoc.managedObjectContext
                            forTheDoc:theDoc] ;

借助克隆技术

- (NSManagedObject *)cloneInContext:(NSManagedObjectContext *)context
                    withCopiedCache:(NSMutableDictionary *)alreadyCopied
                     exludeEntities:(NSArray *)namesOfEntitiesToExclude
                  excludeAttributes:(NSArray *)namesOfAttributesToExclude
{
    NSString *entityName = [[self entity] name];

    if ([namesOfEntitiesToExclude containsObject:entityName])
    {
        return nil;
    }

    NSManagedObject *cloned = [alreadyCopied objectForKey:[self objectID]];
    if (cloned != nil)
    {
        return cloned;
    }


    //create new object in data store
    cloned = [NSEntityDescription insertNewObjectForEntityForName:entityName
                                           inManagedObjectContext:context];
    [alreadyCopied setObject:cloned
                      forKey:[self objectID]];

    //loop through all attributes and assign then to the clone
    NSDictionary *attributes = [[NSEntityDescription entityForName:entityName
                                            inManagedObjectContext:context] attributesByName];


    for (NSString *attr in attributes)
    {
        if (![namesOfAttributesToExclude containsObject:attr])
        {
            [cloned setValue:[self valueForKey:attr] forKey:attr];
        }
    }

    //Loop through all relationships, and clone them.
    NSDictionary *relationships = [[NSEntityDescription entityForName:entityName
                                               inManagedObjectContext:context] relationshipsByName];



    for (NSString *relName in [relationships allKeys])
    {
        NSRelationshipDescription *rel = [relationships objectForKey:relName];

        NSString *keyName = rel.name;

        if ([rel isToMany])
        {
            id sourceSet ;
            id clonedSet ;

            /*
             On gère selon que la relation est ordonnée ou non
             */
            if (![rel isOrdered])
            {
                //get a set of all objects in the relationship
                sourceSet = [self mutableSetValueForKey:keyName];
                clonedSet = [cloned mutableSetValueForKey:keyName];
            }
            else
            {
                sourceSet = [self mutableOrderedSetValueForKey:keyName];
                clonedSet = [cloned mutableOrderedSetValueForKey:keyName];
            }

            NSEnumerator *e = [sourceSet objectEnumerator];
            NSManagedObject *relatedObject;

            while (relatedObject = [e nextObject])
            {
                //Clone it, and add clone to set
                NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context
                                                                     withCopiedCache:alreadyCopied
                                                                      exludeEntities:namesOfEntitiesToExclude
                                                                   excludeAttributes:namesOfAttributesToExclude];
                if (clonedRelatedObject)
                {
                    [clonedSet addObject:clonedRelatedObject];
                }
            }
        }
        else
        {
            NSManagedObject *relatedObject = [self valueForKey:keyName];
            if (relatedObject != nil)
            {
                NSManagedObject *clonedRelatedObject = [relatedObject cloneInContext:context
                                                                     withCopiedCache:alreadyCopied
                                                                      exludeEntities:namesOfEntitiesToExclude
                                                                   excludeAttributes:namesOfAttributesToExclude];
                if (clonedRelatedObject)
                {
                    [cloned setValue:clonedRelatedObject forKey:keyName];
                }
            }
        }
    }

    return cloned;
}