代码之家  ›  专栏  ›  技术社区  ›  Shaggy Frog

是否将现有数据预加载到基于核心数据的iPhone应用程序中?

  •  6
  • Shaggy Frog  · 技术社区  · 16 年前

    在上一个项目中,我为2.2.x构建了一个使用sqlite的iPhone应用程序。它有需要预先加载到构建中的现有数据(XML格式)。所以我编写了一个小工具,它使用libxml2解析XML,然后编写了一个sqlite数据库,该数据库作为资源直接包含在构建中。结果很好。

    我将在几周内为不同的客户启动一个新的项目,这个项目的参数基本相同。我将有一些现有的数据,我将需要分析和转储到应用程序将显示的文件中。不过,这次我想使用核心数据,为3.x设备构建应用程序。但是,我没有对核心数据使用的底层数据库模式的显式和直接访问。(哪种是核心数据点)

    如何将现有数据预加载到基于核心数据的iPhone应用程序中?我可以自动化这个过程吗(类似于我上面用sqlite所做的)?

    4 回复  |  直到 16 年前
        1
  •  3
  •   Ken Mason    16 年前

    假设您使用的是带有SQLite支持的coredata,那么绝对是。最直接的选择是让应用程序为您生成模式,然后使用该空/shell数据库运行XML到SQL迁移工具。您只需要更新您的工具来说明coredata从xcdm为您生成的结构。

    或者,可以使用工具编写包中包含的sqlite db,然后在启动时从sqlite db读取数据,将其吐入coredata,然后继续。这将使用您的sqlite db作为“预加载数据”的容器,以及coredata数据存储中所有进一步的数据交互。

    这可能是一个偏好问题。

        2
  •  10
  •   kalperin    16 年前

    我参加这个聚会有点晚了,但我也在做一些类似的事情。我的coredata sqlite存储中有存储在plist文件中的数据。我编写了一个命令行基础工具,它运行在我的Mac上,它解析PLIST文件,然后使用我的核心数据对象模型创建一个SQLite存储。我运行这个命令行工具作为构建的一部分(对于某些构建配置),以便可以随意重新生成数据。要在Xcode中创建此类工具,请选择文件->新建项目->Mac OS X->命令行工具,然后从“类型”菜单中选择“核心数据”。下面是一些示例代码:

    #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;
    }
    
        3
  •  2
  •   Marc W    16 年前

    我不相信核心数据本身就提供了这种类型的功能。如果我站在你的立场上,我会编写一个小工具来进行XML解析,并根据数据创建核心数据模型并将其持久化。然后,只需将生成的sqlite数据库核心数据移动到实际项目中即可。

    然后,也许可以编写一些代码,将默认数据库复制到iPhone上的适当位置(如果该位置还没有数据库的话)。这也将允许你很容易地恢复到“干净”的数据,如果你进入一个坏的状态,因为你可以删除数据库文件和重新运行应用程序。

        4
  •  2
  •   hallski    16 年前

    你可以采用类似的方法。最简单的方法可能是设置核心数据管理上下文,然后读取XML文件,在解析XML文件时创建托管对象。

        NSManagedObjet *managedObject = [[NSEntityDescription insertNewObjectForEntityForName:@"DataTypeName"
                                                                       inManagedObjectContext:managedContext] retain];
    
        [managedObject setValue:@"some data" forKey:@"keyName"];
        /* ... */