Как предварительно загрузить данные из Core Data в NSPersistentDocument?

У меня есть NSPersistentDocument с заданной моделью Core Data и т. д.

У меня есть файл, созданный этим документом, допустим, это preload.xml. Он «содержит» несколько NSManagedObject.

Я хотел бы загружать эти объекты во все мои новые документы, чтобы при создании нового документа новый документ автоматически «имел» объекты, «живущие» в preload.xml. Пока вот что я сделал:

  • Я скопировал 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.

Мне интересно, нужно ли мне создать новый store или context или storeCoordinator или что-то еще. Я никогда не имел дело с такими объектами, так как всегда использовал NSPersistentDocument.


person Colas    schedule 07.05.2013    source источник
comment
Вы переопределили readFromURL:ofType:error:? Если да, то как выглядит ваша версия?   -  person Tom Harrington    schedule 07.05.2013
comment
Да, я переопределяю readFromURL, но это не работает. Я сделал что-то еще, так как: создал новый store (связанный с моим preload.xml), новый storeCoord и новый MOC. Затем у меня был клон моих объектов между двумя MOC, что не так уж и здорово... Но, похоже, это работает.   -  person Colas    schedule 08.05.2013
comment
Ну, похоже, что исходная проблема каким-то образом связана с вашим кодом readFromURL:ofType:error:, и, поскольку вы не включили его, трудно сказать, что с ним не так.   -  person Tom Harrington    schedule 08.05.2013
comment
Нет, извините, я вообще не переопределял readFromURL !!! Я имел в виду: да, я использовал readFromURL. Извините за недопонимание :/   -  person Colas    schedule 08.05.2013


Ответы (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;
}
person Colas    schedule 23.01.2014