如何在我的项目中创建第二个目标来为 iOS 创建一个预填充的数据库

Posted

技术标签:

【中文标题】如何在我的项目中创建第二个目标来为 iOS 创建一个预填充的数据库【英文标题】:How do I create second target in my project to create a pre-populated database for iOS 【发布时间】:2011-08-17 16:19:38 【问题描述】:

我目前有一个 ios 应用程序,它可以从一堆 pList 文件中“引导”它的数据库(我在开发期间有数据库更改时使用)或复制预先存在的数据库以在设备上首次运行(我使用在模拟器中创建的数据库)。

这变得一团糟:我必须翻转标志来决定我是否正在引导,我不想意外分发“引导”版本,我也不想分发 plist(那么目标设备将拥有 3 个数据副本:捆绑的 db、plist 和 db 的可写副本。

我想做的是创建一个使用相同对象模型的单独桌面应用程序。 plist 将由桌面应用程序使用,我将运行它来生成数据库(或者甚至可能为数据库调整提供 GUI!)。 iPhone 和桌面应用程序将共享相同的数据模型。并且桌面应用程序会写入与 iOS 应用程序捆绑在一起的数据库,所以我不必记得从模拟器中复制。

到目前为止,我已经能够找到一些帖子说这样做很简单......但是教程或提示会有所帮助。

【问题讨论】:

曾经有一个非常方便的技巧,您可以将 CoreData 对象从模型中选择拖动到 nib 文件中以自动生成 UI,但我似乎无法在Xcode 4. :-( 【参考方案1】:

萨沙,

我在现有项目中创建了一个新目标,并且能够创建我的自举核心数据数据库。这一点都不难。您可以重复使用大部分现有代码。

安德鲁

【讨论】:

谢谢安德鲁。听起来您正在做我想做的事,但是我不确定在项目中添加了第二个目标后该怎么做。 (到目前为止,我所有的项目都是非常简单的单目标应用程序)。一旦我创建了第二个目标,您可以提供的任何关于如何设置我的第二个目标的指示(包括在文档中查找的位置,如果这是最简单的)将是最有帮助的。谢谢! Sasha,目标只是代码和构建规则的集合。它在 Apple 的各种 Xcode 文档中有很好的记录。在您的情况下,您希望构建一个应用程序来创建数据库,并以适当的方式设置所有标志。如果您正在构建一个 iOS 应用程序,那么您可能希望在模拟器中运行。完成构建应用程序后,将其与其他资源一起放置,然后编写一些代码将其移出捆绑包并移入文档文件夹。然后它的行为就好像它最初是在那里创建的。安德鲁【参考方案2】:

你有很多选择。您可以创建一个并行应用程序,其唯一职责是在您的主应用程序中预填充数据库。或者您可以使用脚本直接填充数据库文件。我提供了一个很好的教程的链接,该教程描述了后一种方法。

http://www.raywenderlich.com/980/core-data-tutorial-how-to-preloadimport-existing-data

【讨论】:

感谢知觉。 Ray Wenderlinch 有一些非常棒的教程。这个唯一的问题是它让你弄乱了 sqlite 中的模式,这可能有效但不受 Apple 支持,因此可能会在路上咬你。但请相信我,这并不是说我没有受到诱惑,这会容易得多。【参考方案3】:

我看到在我从事的项目中处理这个问题的方式很简单。制作两个目标,并为每个目标配置适当的标志。你会有你的“旗帜翻转”,但不会那么复杂,你可以很容易地分辨出你正在建造哪一个。

【讨论】:

【参考方案4】:

从您的问题看来,您似乎可以在桌面上创建 Core Data Persistent Store。 (这里需要注意的是确保您使用的是共享的核心数据模型。)

鉴于此,您应该将 DB 捆绑为应用程序资源,如果在应用程序启动时找不到它,则将其复制到位。

你应该这样做:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions     

    if (![self persistentStoreExists])  // First run.
        [self copyPersistentStoreFromBundleResources];
    

    // ... continue here.



#pragma mark -
#pragma mark First Run Core Data Import 

- (BOOL)persistentStoreExists

    NSString *storePath = [[[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite" ] path]; 
    NSFileManager *fileManager = [NSFileManager defaultManager];

    return [fileManager fileExistsAtPath:storePath];


- (void)copyPersistentStoreFromBundleResources

    NSLog(@"Installing default DB from bundle.");

    NSString *storePath = [[[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite" ] path];

    NSString *defaultStorePath = [[NSBundle mainBundle] 
                                  pathForResource:@"MyApp" ofType:@"sqlite"];

    if (defaultStorePath == nil) 
        NSLog(@"Error finding default store");
        return;
     else 
        BOOL copiedDefaultStore = [[NSFileManager defaultManager]
                                   copyItemAtPath:defaultStorePath
                                   toPath:storePath
                                   error:nil];
        if (! copiedDefaultStore) 
            NSLog(@"Error copying default store");
            return;
        
    


#pragma mark -
#pragma mark Application's Documents directory

/**
 Returns the URL to the application's Documents directory.
 */
- (NSURL *)applicationDocumentsDirectory 
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

【讨论】:

谢谢卡尔顿。如果数据库不存在,我的启动代码可以正常工作以复制数据库(尽管乍一看你在这里得到的东西看起来更干净,但我可能会改用它)。我遇到的问题是首先生成数据库,并在两个应用程序之间共享数据模型。我会在原来的问题中澄清这一点......

以上是关于如何在我的项目中创建第二个目标来为 iOS 创建一个预填充的数据库的主要内容,如果未能解决你的问题,请参考以下文章

在 OpenGL 4 中创建第二个 VAO 并绘制两个形状

在 R Shiny 中创建第二个 UI 元素

IDEA 在同一工作空间创建多个项目

11. IDEA 在同一工作空间创建多个项目

如何在sqlite的数据库中添加第二个表?

c ++在第一类的构造函数中创建第二类的对象 - 多线程