如何将核心数据添加到现有的iPhone项目?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (36)

我想将核心数据添加到现有的iPhone项目中,但我仍然遇到很多编译错误:

- NSManagedObjectContext undeclared

 - Expected specifier-qualifier-list before 'NSManagedObjectModel'

 - ...

我已经将Core Data Framework添加到目标中(在“目标”,“添加” - “现有框架”,“CoreData.framework”)下右键单击我的项目。

我的头文件:

NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;       
NSPersistentStoreCoordinator *persistentStoreCoordinator;

[...]

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

我错过了什么?开始一个新项目不是一个选择......

提问于
用户回答回答于

所有的CoreData头文件都被导入App_Prefix.pch,所以CoreData类将在您的项目中可用,因此您不必手动将文件头导入需要它们的文件中。

因此,打开Xcode并查找一些文件App_Prefix.pch,默认情况下它位于Other Sources组中。在UIKit导入语句之后,添加以下行:

#import <CoreData/CoreData.h>

你应该准备好去。

Xcode 4

对于在Xcode 4中创建的项目,可以Supporting Files在项目导航器的组中找到前缀文件。它默认被称为' projectname -Prefix.pch'。

Xcode 6+

从Xcode 6开始,默认情况下不再包含预编译头文件。这是因为引入了模块,这就消除了使用预编译头文件的需要。虽然仍可以手动添加PCH文件以全局包含CoreData标题,但可以考虑@import CoreData;在每个使用CoreData的文件中使用* 指定CoreData依赖项。这使得依赖关系更加明确,更重要的是将来避免这个问题的问题。

用户回答回答于

第1步:添加框架

点击你的应用程序目标(在左边的窗格上显示你的应用程序名称的顶部图标),然后进入“构建阶段”选项卡,然后点击“与库链接二进制文件”,点击底部的小'+',然后找到'CoreData.framework'并将其添加到您的项目中

然后,使用以下命令将coredata导入所有需要的对象(非性感方式):

迅速

import CoreData

目标C

#import <CoreData/CoreData.h>

或者在您的.pch文件中的常见导入下方添加导入(更性感),如下所示:

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

第2步:添加数据模型

要添加.xcdatamodel文件,请右键单击/右键单击右侧窗格中的文件(如Resources文件夹中的安全保存),然后选择添加新文件,选择文件类型时单击Core Data选项卡,然后单击“数据模型“,给它一个名字并点击下一步和完成,它会将它添加到你的项目中。当你点击这个模型对象时,你会看到一个界面,用你想要的任何关系将实体添加到你的项目中。

第3步:更新应用程序委托

Swift上AppDelegate.swift

//replace the previous version of applicationWillTerminate with this
func applicationWillTerminate(application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    // Saves changes in the application's managed object context before the application terminates.
    self.saveContext()
}

func saveContext () {
    var error: NSError? = nil
    let managedObjectContext = self.managedObjectContext
    if managedObjectContext != nil {
        if managedObjectContext.hasChanges && !managedObjectContext.save(&error) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            //println("Unresolved error \(error), \(error.userInfo)")
            abort()
        }
    }
}

// #pragma mark - Core Data stack

// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
var managedObjectContext: NSManagedObjectContext {
    if !_managedObjectContext {
        let coordinator = self.persistentStoreCoordinator
        if coordinator != nil {
            _managedObjectContext = NSManagedObjectContext()
            _managedObjectContext!.persistentStoreCoordinator = coordinator
        }
    }
    return _managedObjectContext!
}
var _managedObjectContext: NSManagedObjectContext? = nil

// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
var managedObjectModel: NSManagedObjectModel {
    if !_managedObjectModel {
        let modelURL = NSBundle.mainBundle().URLForResource("iOSSwiftOpenGLCamera", withExtension: "momd")
        _managedObjectModel = NSManagedObjectModel(contentsOfURL: modelURL)
    }
    return _managedObjectModel!
}
var _managedObjectModel: NSManagedObjectModel? = nil

// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
var persistentStoreCoordinator: NSPersistentStoreCoordinator {
    if !_persistentStoreCoordinator {
        let storeURL = self.applicationDocumentsDirectory.URLByAppendingPathComponent("iOSSwiftOpenGLCamera.sqlite")
        var error: NSError? = nil
        _persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        if _persistentStoreCoordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error) == nil {
            /*
            Replace this implementation with code to handle the error appropriately.
            abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            Typical reasons for an error here include:
            * The persistent store is not accessible;
            * The schema for the persistent store is incompatible with current managed object model.
            Check the error message to determine what the actual problem was.
            If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
            If you encounter schema incompatibility errors during development, you can reduce their frequency by:
            * Simply deleting the existing store:
            NSFileManager.defaultManager().removeItemAtURL(storeURL, error: nil)
            * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
            [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true}
            Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
            */
            //println("Unresolved error \(error), \(error.userInfo)")
            abort()
        }
    }
    return _persistentStoreCoordinator!
}
var _persistentStoreCoordinator: NSPersistentStoreCoordinator? = nil

// #pragma mark - Application's Documents directory

// Returns the URL to the application's Documents directory.
var applicationDocumentsDirectory: NSURL {
    let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.endIndex-1] as NSURL
}

Objective C中,确保将这些对象添加到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];
}

第4步:将数据对象获取到需要数据的ViewControllers

选项1.使用VC中的App Delegate的ManagedObjectContext(首选和更简单)

通过以下方法检索对AppDelegate及其managedObjectContext的引用:

迅速

 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
 appDelegate.managedObjectContext

目标C

 [[[UIApplication sharedApplication] delegate] managedObjectContext];

在你的ViewController中

选项2.在VC中创建ManagedObjectContext并使其与AppDelegate中的AppDelegate匹配(原始)

仅显示Objective C的旧版本,因为使用首选方法更容易

在ViewController.h中

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

在ViewController.m中

@synthesize managedObjectContext = _managedObjectContext;

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

ViewController.managedObjectContext = self.managedObjectContext;

如果你想使用核心数据的viewcontroller是一个FetchedResultsController,那么你需要确保这些东西在你的ViewController.h中

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

 @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;

这是在ViewController.m中

@synthesize fetchedResultsController, managedObjectContext;

毕竟,您现在可以使用此managedObjectContext来运行CoreData所需的所有常用fetchRequests!请享用

扫码关注云+社区