Предварительно загрузить существующие данные в приложение для iPhone на основе Core Data?

В предыдущем проекте я создал приложение для iPhone для версии 2.2.x, в котором использовался SQLite. В нем были существующие данные (в форме XML), которые необходимо было предварительно загрузить в сборку. Поэтому я написал небольшой инструмент, который использовал libxml2 для анализа XML, а затем записал базу данных SQLite, которая затем была включена непосредственно в сборку в качестве ресурса. Это отлично сработало.

Через несколько недель я начну новый проект для другого клиента, который будет иметь в основном те же параметры. У меня будут некоторые существующие данные, которые мне нужно будет проанализировать и выгрузить в файл, который будет отображать приложение. Однако на этот раз я хотел бы использовать Core Data и создать приложение для устройств 3.x. Однако у меня нет явного и прямого доступа к базовой схеме базы данных, которую использует Core Data. (В чем суть Core Data)

Как я могу предварительно загрузить существующие данные в приложение iPhone на основе Core Data? Могу ли я автоматизировать процесс (аналогично тому, что я сделал выше с SQLite)?


person Shaggy Frog    schedule 19.11.2009    source источник


Ответы (4)


Если вы используете CoreData с поддержкой SQLite, тогда абсолютно. Самым прямым вариантом было бы позволить приложению сгенерировать схему для вас, а затем, используя эту пустую базу данных / оболочку, запустить инструмент миграции xml-to-sql. Вам просто нужно обновить свой инструмент, чтобы учесть структуру, которую CoreData генерирует для вас из xcdm.

В качестве альтернативы вы можете использовать свой инструмент для написания sqlite db, который включен в ваш пакет, затем во время выполнения при запуске, прочитать данные из sqlite db, выплюнуть их в CoreData и продолжить. Это будет использовать вашу базу данных sqlite в качестве контейнера для «данных предварительной загрузки» и всего дальнейшего взаимодействия с данными в хранилище данных CoreData.

Наверное, дело предпочтений.

person Ken Mason    schedule 19.11.2009
comment
Под приложением вы имеете в виду позволить Xcode генерировать схему? Или схема создается только во время выполнения? - person Shaggy Frog; 21.11.2009
comment
Я не уверен на 100%. Я хочу сказать, что он генерируется во время выполнения (я считаю, что часть инициализации CoreData предназначена для обновления хранилища данных, если это необходимо), но вам нужно будет дважды проверить это. - person Ken Mason; 21.11.2009
comment
Xcode не будет генерировать схему. Это операция во время выполнения. - person Marc W; 21.11.2009

Я немного опоздал на эту вечеринку, но я делаю нечто подобное для GroceryList. У меня есть данные, хранящиеся в файлах plist, которые мне нужны в моем хранилище CoreData sqlite. Я написал базовый инструмент командной строки, который работает на моем Mac, который анализирует файлы plist, а затем с помощью моей объектной модели Core Data создает хранилище sqlite. Я запускаю этот инструмент командной строки как часть моей сборки (для некоторых конфигураций сборки), чтобы я мог восстанавливать данные по своему желанию. Чтобы создать такой инструмент в xcode, выберите File -> New Project -> Mac OS X -> Command Line Tool и выберите «Core Data» из меню «type». Вот пример кода:

#import <objc/objc-auto.h>

int main (int argc, const char * argv[]) {

    objc_startCollectorThread();

    //You may not know this, but NSUserDefaults can be used to parse command line arguments!
    //in this case, the arguments are passed in like this:
    // -fullMomPath /hd/some/path/file.mom -fullStorePath /hd/some/path/file.sql
    //by passing in the storePath, the calling script knows where the sqlite file will be and can copy it to the resulting application bundle
    NSUserDefaults *args = [NSUserDefaults standardUserDefaults];   
    NSString *momPath = [args stringForKey:@"fullMomPath"];
    NSString *storePath = [args stringForKey:@"fullStorePath"];

    // Create the managed object context
    NSManagedObjectContext *context = managedObjectContext(momPath, storePath);


    //build and save your NSManagedObjects here
    //in my case, i parse some plist files and create GroceryList type stuff, but whatever you do is your business.

    return 0;
}

NSManagedObjectModel *managedObjectModel(NSString* momPath) {

    static NSManagedObjectModel *model = nil;

    if (model != nil) {
        return model;
    }

    NSURL *modelURL = [NSURL fileURLWithPath:momPath];
    model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];

    return model;
}



NSManagedObjectContext *managedObjectContext(NSString* momPath, NSString* storePath) {

    static NSManagedObjectContext *context = nil;
    if (context != nil) {
        return context;
    }

    context = [[NSManagedObjectContext alloc] init];

    NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: managedObjectModel(momPath)];
    [context setPersistentStoreCoordinator: coordinator];

    NSString *STORE_TYPE = NSSQLiteStoreType;

    NSURL *url = [NSURL fileURLWithPath:storePath];

    NSError *error;
    NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:STORE_TYPE configuration:nil URL:url options:nil error:&error];

    if (newStore == nil) {
        NSLog(@"Store Configuration Failure\n%@",
              ([error localizedDescription] != nil) ?
              [error localizedDescription] : @"Unknown Error");
    }

    return context;
}
person kalperin    schedule 12.01.2010
comment
Эй, спасибо, что поделились! Однако у меня возникли проблемы с определением пути MOM. См. stackoverflow.com/questions/4600312/ Спасибо! - person Stunner; 05.01.2011

Я не верю, что Core Data по своей сути обеспечивает такую ​​функциональность. Если бы я был на вашем месте, я бы написал небольшой инструмент, который выполнял бы синтаксический анализ XML и делал все необходимое для создания модели Core Data из этих данных и ее сохранения. Затем просто переместите базу данных sqlite, созданную Core Data, в свой настоящий проект.

Затем, возможно, напишите код, который копирует эту базу данных по умолчанию в нужное место на iPhone, если база данных там еще не существует. Это также позволит вам легко вернуться к «чистым» данным, если вы попадете в плохое состояние, поскольку вы можете просто удалить файл базы данных и повторно запустить приложение.

person Marc W    schedule 19.11.2009
comment
На самом деле я сделал что-то похожее на то, что вы описали, но вместо того, чтобы делать это в два этапа, я делаю это за один. Я создаю магазин .sql там, где он нужен в айфоне. Однако не вызовет ли этот подход проблем, когда пришло время отправить приложение в магазин приложений? Как бы вы исправили эту проблему? - person Stunner; 22.01.2011
comment
Почему это может вызвать проблемы? Я не думаю, что включение исходных данных в ваше приложение противоречит правилам App Store. - person Marc W; 22.01.2011

Вы можете использовать аналогичный подход. Самый простой способ - настроить управляемый контекст основных данных, а затем прочитать его в XML-файле, создав управляемые объекты по мере анализа XML-файла.

    NSManagedObjet *managedObject = [[NSEntityDescription insertNewObjectForEntityForName:@"DataTypeName"
                                                                   inManagedObjectContext:managedContext] retain];

    [managedObject setValue:@"some data" forKey:@"keyName"];
    /* ... */
person hallski    schedule 19.11.2009
comment
Это верное решение. Однако я бы предпочел выполнять такой анализ в автономном режиме, поэтому приложение всегда видит только файл базы данных SQLite. - person Shaggy Frog; 21.11.2009