如何在我的项目中创建第二个目标,以便为iOS创建预先填充的数据库

时间:2023-01-13 13:36:17

I currently have an iOS app that can 'bootstrap' it's database from a bunch of pList files (which I use during development when there are db changes) or copy a pre-existing database for the first run on a device (I use the database that was created in the simulator).

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

This is getting messy: I have to flip flags to decide whether I'm bootstrapping or not, I don't want to distribute a 'bootstrap' version by accident, and I don't want to distribute the plists either (then the target device would have 3 copies of the data: the bundled db, the plists, and the writeable copy of the db).

这变得很乱:我必须翻转标志来决定我是否自举,我不想意外地分发'bootstrap'版本,我也不想分发plist(然后是目标设备将有3个数据副本:捆绑的数据库,plist和db的可写副本。

What I would like to do is create a separate desktop app that uses the same object model. The plists would be used by the desktop app, which I would run to generate the db (or maybe even provide a GUI for DB tweaks!). The iPhone and desktop app would share the same data model. And the desktop app would write to the db that's bundled with the iOS app, so I don't have to remember to copy from the simulator.

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

So far, I have been able to find posts that say that this would be trivial to do... but a tutorial or tips would be helpful.

到目前为止,我已经能够找到一些帖子,说这将是微不足道的...但教程或提示会有所帮助。

4 个解决方案

#1


1  

Sasha,

I made a new target in my existing project and was able to create my bootstrapped Core Data DB. It wasn't hard at all. You reuse most of your existing code.

我在现有项目中创建了一个新目标,并且能够创建我的自举Core Data DB。这根本不难。您重用了大部分现有代码。

Andrew

#2


0  

You have many options. You can create a side-by-side application whose sole responsibility is to pre-populate the DB in your main app. Or you can use a script to populate the DB file directly. I am including a link to a nice tutorial that describes the latter approach.

你有很多选择。您可以创建一个并排应用程序,其唯一的职责是在主应用程序中预先填充数据库。或者您可以使用脚本直接填充DB文件。我正在包含一个描述后一种方法的精彩教程的链接。

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

#3


0  

The way I've seen this problem dealt with in projects that I've worked on is simple. Make two targets, and configure each one with the appropriate flags. You'll have your "flag flipping", but won't be quite as complicated and you'll be able to easily tell which one you are building.

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

#4


0  

From your question it sounds as if you can create the Core Data Persistent Store on the desktop. (The caveat here is to ensure you are using a shared Core Data Model.)

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

Given that, you should bundle the DB as an application resource and copy it into place if it is not found at application startup.

鉴于此,您应该将数据库捆绑为应用程序资源,并在应用程序启动时找不到它并将其复制到位。

Something like this should do you:

这样的事情应该对你有用:

- (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];
}

#1


1  

Sasha,

I made a new target in my existing project and was able to create my bootstrapped Core Data DB. It wasn't hard at all. You reuse most of your existing code.

我在现有项目中创建了一个新目标,并且能够创建我的自举Core Data DB。这根本不难。您重用了大部分现有代码。

Andrew

#2


0  

You have many options. You can create a side-by-side application whose sole responsibility is to pre-populate the DB in your main app. Or you can use a script to populate the DB file directly. I am including a link to a nice tutorial that describes the latter approach.

你有很多选择。您可以创建一个并排应用程序,其唯一的职责是在主应用程序中预先填充数据库。或者您可以使用脚本直接填充DB文件。我正在包含一个描述后一种方法的精彩教程的链接。

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

#3


0  

The way I've seen this problem dealt with in projects that I've worked on is simple. Make two targets, and configure each one with the appropriate flags. You'll have your "flag flipping", but won't be quite as complicated and you'll be able to easily tell which one you are building.

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

#4


0  

From your question it sounds as if you can create the Core Data Persistent Store on the desktop. (The caveat here is to ensure you are using a shared Core Data Model.)

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

Given that, you should bundle the DB as an application resource and copy it into place if it is not found at application startup.

鉴于此,您应该将数据库捆绑为应用程序资源,并在应用程序启动时找不到它并将其复制到位。

Something like this should do you:

这样的事情应该对你有用:

- (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];
}