在XCode 4中将Core Data添加到现有项目

26

我在项目开始时没有使用Core Data,现在想要在我的应用程序中添加这个功能。我该怎么做?

当您创建一个新项目并勾选使用Core Data时,XCode会设置哪些附加内容?


1
可能是将Core Data添加到现有的iPhone项目的重复问题。 - Michael Dautermann
6个回答

42

一个技巧是创建一个带有 Core Data 支持的新空项目,这将为您提供必要的代码,您可以将其复制到原始项目中并进行编译。

唯一需要注意的是您需要处理 Core Data 的头文件。Xcode 在使用模板生成文件时将其放在预编译头文件中。因此,您可以在 .pch 文件中添加以下行:

#import <CoreData/CoreData.h>
或者您可以将其添加到需要的 .m 文件中。
它工作得很好。请注意,Luka 在下面的评论中提到如何在 Xcode5 中进行操作。

2
抱歉如果我表达不清楚 - 这个想法是从Xcode生成的纯模板中复制有用的代码。您可以保留所有现有的Xcode项目。 - Monolo
2
我认为让人们知道在Xcode的Single View Based Application模板中,“使用Core Data”选项是不可用的,可能会有所帮助。您必须选择Empty Application模板。 - Shea Daniels
2
不要忘记添加CoreData框架。在Xcode 4.6中:在项目导航器中,单击您的项目,在Targets下找到您的应用程序,在Summary选项卡中,在Linked Frameworks and Libraries中点击加号。 - abc123
@SKG 谢谢您指出需要链接框架的问题。不过,我不知道您所说的更改字符串名称是什么意思。我在我的项目中搜索了这些名称,但没有发现任何可疑的地方。能否请您澄清一下? - mkc842
1
在Xcode 5.0中,您可以选择“主细节应用程序”或“空应用程序”模板,以获取“使用核心数据”选项,并生成核心数据代码。 - lgdev
显示剩余4条评论

19

为了阐明在之前未使用Core Data的项目中实际所需执行的所有步骤:

第一步:添加框架

单击应用程序目标(在左侧窗格中,它是具有您应用程序名称的顶部图标),然后转到“构建阶段”选项卡,然后在“链接二进制文件与库”下,单击底部的小“+” ,然后找到“CoreData.framework”并将其添加到您的项目中。

然后,在您需要它的所有对象上导入coredata(非常规方法),使用以下语句:

#import <CoreData/CoreData.h>

或者将此导入语句添加到您的.pch文件中普通导入语句之下(更加优雅):

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
#endif

步骤2:添加数据模型

要添加.xcdatamodel文件,请在右侧窗格中右键单击/控制单击您的文件(例如资源文件夹),然后选择添加新文件,选择文件类型时点击Core Data选项卡,然后点击“数据模型”,给它命名并点击下一步和完成即可将其添加到项目中。当您单击此模型对象时,您将看到添加实体及其任何关系到项目中的接口。

步骤3:更新App Delegate

请将这些对象添加到AppDelegate.h中。

 @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
 @property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
 @property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

 - (NSURL *)applicationDocumentsDirectory; // nice to have to reference files for core data

在AppDelegate.m中综合之前的对象,就像这样:

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

然后在AppDelegate.m中添加这些方法(确保在所示的位置放置您添加的模型的名称):

- (void)saveContext{
    NSError *error = nil;
    NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    if (managedObjectContext != nil) {
        if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
}

- (NSManagedObjectContext *)managedObjectContext{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}

- (NSManagedObjectModel *)managedObjectModel{
    if (_managedObjectModel != nil) {
        return _managedObjectModel;
    }
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"NAMEOFYOURMODELHERE" withExtension:@"momd"];
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    return _managedObjectModel;
}

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"NAMEOFYOURMODELHERE.sqlite"];

    NSError *error = nil;
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }

    return _persistentStoreCoordinator;
}

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

步骤四:将数据对象传递到需要使用数据的视图控制器中

在ViewController.h文件中

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

在ViewController.m文件中

@synthesize managedObjectContext = _managedObjectContext;

在AppDelegate或创建ViewController的类中,将managedObjectContext设置为与AppDelegate相同的对象。

ViewController.managedObjectContext = self.managedObjectContext;

如果您希望使用Core Data的视图控制器成为一个FetchedResultsController,那么您需要确保这些内容包含在您的ViewController.h中。

@interface ViewController : UIViewController <NSFetchedResultsControllerDelegate> {
  NSFetchedResultsController *fetchedResultsController;
  NSManagedObjectContext *managedObjectContext;
}

 @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

这是在ViewController.m文件中

@synthesize fetchedResultsController, managedObjectContext;

在完成上述步骤后,您现在可以使用此managedObjectContext运行所有常规的fetchRequests,以便享受CoreData带来的好处!祝您使用愉快


很好的答案,需要注意的一点是在appDelegate头文件中,方法- (NSString *)applicationDocumentsDirectory; 应该改为 - (NSURL *)applicationDocumentsDirectory;。否则它将无法匹配 - (NSPersistentStoreCoordinator *)persistentStoreCoordinator 中的代码。我已经编辑了更新后的代码。 - Peng90
1
感谢您提供这些完整的指示。这应该是正确的答案。 - SushiGrass Jacob

2

如果你想在项目中添加CoreData.framework,双击“Groups and Files”列表中的目标。进入“Summary”面板,点击“Linked Libraries”的“+”号。选择CoreData.framework并将其链接到你的项目中。


1

Xcode会在Core Data的标准模板中添加一堆东西。

如果您不熟悉它,请创建一个新的Core Data项目,并将自己的内容推入其中,而不是尝试将基础设施添加到现有项目中。

基本上你会得到...

  • 一个空的Core Data模型。
  • 用于Core Data堆栈的初始化代码

取决于您是使用文档架构还是简单的基于视图的应用程序。您可能还需要设置一些info.plist。生成一个并进行探索。 - Warren Burton

0

我发现最简单的方法是创建一个带有核心数据的新项目,删除项目中的文件,然后从非核心数据项目拖放到核心数据项目中(例如Main.storyboard、AppDelegate、ViewController等)。


0

通过将其与包含 Core Data 的新项目进行比较,向您的项目添加 Core Data 真的很简单。您需要添加一个“数据模型”文件以及一些方法和 ivars 到 AppDelegate 中。

查看实现文件中的 Core Data 项目模板 ->“Core Data stack”。


它是否修改了任何项目构建设置? - adit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接