将核心数据添加到现有的iPhone项目中

swa*_*ner 138 core-data ios

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

- NSManagedObjectContext undeclared

 - Expected specifier-qualifier-list before 'NSManagedObjectModel'

 - ...
Run Code Online (Sandbox Code Playgroud)

我已经将核心数据框架添加到目标(右键单击我的项目"Targets","Add" - "Existing Frameworks","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;
Run Code Online (Sandbox Code Playgroud)

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

非常感谢!

编辑 对不起,我确实有这些实现...但似乎缺少库...实现方法已满,编译错误如" managedObjectContext undeclared"," NSPersistentStoreCoordinator undeclared",但也有"预期")'之前NSManagedObjectContext"(虽然它似乎括号是正确的)...

#pragma mark -
#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.
 */
- (NSManagedObjectContext *) managedObjectContext {

    if (managedObjectContext != nil) {
        return managedObjectContext;
    }

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


/**
 Returns the managed object model for the application.
 If the model doesn't already exist, it is created by merging all of the models found in    
 application bundle.
 */
- (NSManagedObjectModel *)managedObjectModel {

    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];    
    return managedObjectModel;
}


/**
 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.
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {

    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }

    NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] 
        stringByAppendingPathComponent: @"Core_Data.sqlite"]];

    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] 
    initWithManagedObjectModel:[self managedObjectModel]];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 
    configuration:nil URL:storeUrl options:nil error:&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. If it is not possible to recover from the error, display an alert panel that 
    instructs the user to quit the application by pressing the Home button.

     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.
     */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();
}    

return persistentStoreCoordinator;
}
Run Code Online (Sandbox Code Playgroud)

Joo*_*ost 145

导入了所有CoreData头文件App_Prefix.pch,因此CoreData类将在整个项目中可用,因此您无需在所需文件中手动导入标头.

所以打开Xcode并查找一些文件App_Prefix.pch,默认情况下它在Other Sources组中.在UIKitimport语句之后,添加以下行:

#import <CoreData/CoreData.h>
Run Code Online (Sandbox Code Playgroud)

你应该准备好了.

Xcode 4

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

Xcode 6+

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

*需要启用模块才能使其正常工作.


Col*_*ris 127

只是为了阐述您实际需要执行的所有步骤,以将Core Data添加到以前没有它的项目中:

第1步:添加框架

点击您的应用目标(在左侧窗格中与您的应用程序的名称上方的图标),然后进入到"构建阶段"选项卡,然后在"链接二进制与图书馆",点击小"+"的底部,然后找到'CoreData.framework'并将其添加到您的项目中

然后使用以下方法在您需要的所有对象上导入coredata(非性感方式):

迅速

import CoreData
Run Code Online (Sandbox Code Playgroud)

目标C.

#import <CoreData/CoreData.h>
Run Code Online (Sandbox Code Playgroud)

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

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    #import <CoreData/CoreData.h>
#endif
Run Code Online (Sandbox Code Playgroud)

第2步:添加数据模型

要添加.xcdatamodel文件,请右键单击/按住Control键并单击右侧窗格中的文件(如在"资源"文件夹中保存),然后选择"添加新文件",在选择文件类型时单击"核心数据"选项卡,然后单击"确定".数据模型',给它一个名称,然后单击下一步和完成,它将把它添加到您的项目中.当您单击此Model对象时,您将看到用您想要的任何关系将实体添加到项目的界面.

第3步:更新App Delegate

在AppDelegate.swift上的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
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

像这样合成AppDelegate.m中的前一个对象:

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
Run Code Online (Sandbox Code Playgroud)

然后将这些方法添加到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];
}
Run Code Online (Sandbox Code Playgroud)

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

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

正如@ brass-kazoo所建议的那样 - 通过以下方式检索对AppDelegate及其managedObjectContext的引用:

迅速

 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
 appDelegate.managedObjectContext
Run Code Online (Sandbox Code Playgroud)

目标C.

 [[[UIApplication sharedApplication] delegate] managedObjectContext];
Run Code Online (Sandbox Code Playgroud)

在您的ViewController中

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

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

在ViewController.h中

@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
Run Code Online (Sandbox Code Playgroud)

在ViewController.m中

@synthesize managedObjectContext = _managedObjectContext;
Run Code Online (Sandbox Code Playgroud)

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

ViewController.managedObjectContext = self.managedObjectContext;
Run Code Online (Sandbox Code Playgroud)

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

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

 @property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
Run Code Online (Sandbox Code Playgroud)

这是在ViewController.m中

@synthesize fetchedResultsController, managedObjectContext;
Run Code Online (Sandbox Code Playgroud)

完成所有这些之后,您现在可以使用此managedObjectContext来运行CoreData良好所需的所有常用fetchRequests!请享用

  • 这是IMO的最佳答案!虽然代替第4步,我通过`[[UIApplication sharedApplication]委托]检索了对AppDelegate的引用,然后通过`[appDelegate managedObjectContext]检索了上下文. (9认同)
  • 在AppDelegate.h中,applicationDoumentsDirectory方法应返回NSURL而不是NSString. (2认同)

kur*_*odu 16

对于Swift 3:包括保存和检索数据

第1步:添加框架

在此输入图像描述

在此输入图像描述

第2步:添加数据模型

文件>新建>文件>核心数据>数据模型

  • 将文件命名为SampleData结果文件SampleData.xcdatamocelId

步骤3:将以下功能添加到App Delegate,并将"import CoreData"添加到顶部

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()
}


// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = {
    /*
     The persistent container for the application. This implementation
     creates and returns a container, having loaded the store for the
     application to it. This property is optional since there are legitimate
     error conditions that could cause the creation of the store to fail.
     */


    // SEE BELOW LINE OF CODE WHERE THE 'name' IS SET AS THE FILE NAME (SampleData) FOR THE CONTAINER

    let container = NSPersistentContainer(name: "SampleData")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() 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 parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() 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.
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

第4:向模型添加实体和属性

a)添加实体 在此输入图像描述

b)添加属性 在此输入图像描述

第5:保存数据

func saveItem(itemToSave: String){
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

//**Note:** Here we are providing the entityName **`Entity`** that we have added in the model
    let entity = NSEntityDescription.entity(forEntityName: "Entity", in: context)
    let myItem = NSManagedObject(entity: entity!, insertInto: context)

    myItem.setValue(itemToSave, forKey: "item")
    do {
        try context.save()
    }
    catch{
        print("There was an error in saving data")
    }
}
Run Code Online (Sandbox Code Playgroud)

第5:检索数据

override func viewWillAppear(_ animated: Bool) {
    // Obtaining data from model
    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Entity")

    do {
        let results = try context.fetch(fetchRequest)
        let obtainedResults = results as! [NSManagedObject]
        let firstResult = obtainedResults[0]
        let myValue = firstResult.value(forKey: "item")

        print("myValue: \(myValue)")
    } catch {
        print("Error")
    }
}
Run Code Online (Sandbox Code Playgroud)


Eim*_*tas 11

尝试创建Core Data支持的Cocoa应用程序并查看AppDelegate.您将看到核心数据堆栈实现方法以及用于定义实体和其他核心数据相关内容的托管对象模型文件.

您只向我们展示了头文件(即声明),但没有向我们展示核心数据堆栈的实现(即定义).


小智 8

如果你在xcode 4中遇到同样的问题,就像我一样.它是不同的:我必须选择项目,然后在目标中展开"Link Binary With Libraries",它显示了当前的库.从那里单击+(加号)以选择您需要的任何其他库.我把它放在项目的顶部,不得不将它(拖放)移动到框架组,但就是这样.


Hen*_*sel 5

正如Eimantas所说,你错过了核心堆栈的实现,就像

- (NSManagedObjectContext *) managedObjectContext;
- (NSManagedObjectModel *)managedObjectMode;
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator;
Run Code Online (Sandbox Code Playgroud)

解决方案是创建一个新的核心数据驱动程序项目,并将实现复制/粘贴到您的项目中.

  • 那么如何管理上下文会意识到模型?自动? (2认同)