核心数据不会持久保存对象

San*_*eja 17 core-data objective-c ios ios6

我是Core Data的新手,因此我不确定我是否犯了错误.我从REST API下载了一些数据,并成功将JSON响应保存到磁盘.我正在尝试处理数据并使用Core Data持久保存数据.

NSLog(@"inserted objects: %@", [managedObjectContext insertedObjects]);
    [managedObjectContext performBlockAndWait:^{
        NSError *error = nil;
        if (![managedObjectContext save:&error]) {
            NSLog(@"Unable to save context for class %@", className);
        } else {
            NSLog(@"saved all records!");
        }
    }];
Run Code Online (Sandbox Code Playgroud)

我已成功处理JSON并将其添加到NSManagedObjectContext.在第一行中,它显示我已成功尝试插入2个对象.

inserted objects: {(
    <User: 0xa259af0> (entity: User; id: 0xa259b70 <x-coredata:///User/t44BB97D0-C4B4-4BA6-BD25-13CEFDAE665F3> ; data: {
    email = "vishnu@vishnuprem.com";
    experience = "2013-07-20";
    "first_name" = Vishnu;
    id = 2;
    "job_title" = Developer;
    "last_name" = Prem;
    location = "";
    "phone_number" = "+6590091516";
    "profile_pic" = "";
    "thumbnail_profile_pic" = "";
    "user_id" = 2;
}),
    <User: 0xa25e460> (entity: User; id: 0xa25e4c0 <x-coredata:///User/t44BB97D0-C4B4-4BA6-BD25-13CEFDAE665F2> ; data: {
    email = "sanchitbareja@gmail.com";
    experience = "2013-07-20";
    "first_name" = Sanchit;
    id = 1;
    "job_title" = Developer;
    "last_name" = Bareja;
    location = "";
    "phone_number" = "+15106127328";
    "profile_pic" = "";
    "thumbnail_profile_pic" = "";
    "user_id" = 1;
})
)}
Run Code Online (Sandbox Code Playgroud)

当我尝试时[managedObjectContext save:&error],它成功完成并按预期打印出"保存所有记录".但是,当我转到我的应用程序.sqlite文件并检查添加的对象时,我意识到它没有向db添加任何对象.

在应用程序重新启动时,我打印出已存在于数据库中的对象列表,并确认我尚未保存.

有没有人知道发生了什么以及为什么我无法持久保存数据,即使看起来我已经成功创建了需要保存在Core Data模型中的'User'对象.

编辑:

这是我创建的地方 NSPersistentStoreCoordinator

// 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 = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"RTModel.sqlite"];

    NSError *error = nil;
    NSLog(@"Test 1");
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSLog(@"Test 2");

    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.

         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:
         [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];

         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.

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

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

我有3个上下文.

  • masterManagedObjectContext

  • backgroundManagedObjectContext

  • newManagedObjectContext

master是后台和新后台的父级.当我查询这样的上下文时:

    NSError *error = nil;
    NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"User"];
    [request setSortDescriptors:[NSArray arrayWithObject:
                                 [NSSortDescriptor sortDescriptorWithKey:@"id" ascending:YES]]];
    [request setReturnsObjectsAsFaults:NO];
    NSArray *testArray = [[[RTCoreDataController sharedInstance] newManagedObjectContext] executeFetchRequest:request error:&error];

    for (User *obj in testArray) {
        NSLog(@"obj.id %@", obj.id);
    }

    NSLog(@"query records: %@",testArray);
Run Code Online (Sandbox Code Playgroud)

master和background都在NSLog中返回正确的obj.id,并为@"查询记录"提供下面的输出

   (
    "<User: 0xa3811d0> (entity: User; id: 0xa381230 <x-coredata:///User/t92BCED2D-CD17-49CC-9EBA-DF8F52F06A002> ; data: {\n    email = \"sanchitbareja@gmail.com\";\n    experience = \"2013-07-20\";\n    \"first_name\" = Sanchit;\n    id = 1;\n    \"job_title\" = Developer;\n    \"last_name\" = Bareja;\n    location = \"\";\n    \"phone_number\" = \"+15106127328\";\n    \"profile_pic\" = \"\";\n    \"thumbnail_profile_pic\" = \"\";\n    \"user_id\" = 1;\n})",
    "<User: 0xa382170> (entity: User; id: 0xa3820b0 <x-coredata:///User/t92BCED2D-CD17-49CC-9EBA-DF8F52F06A003> ; data: {\n    email = \"vishnu@vishnuprem.com\";\n    experience = \"2013-07-20\";\n    \"first_name\" = Vishnu;\n    id = 2;\n    \"job_title\" = Developer;\n    \"last_name\" = Prem;\n    location = \"\";\n    \"phone_number\" = \"+6590091516\";\n    \"profile_pic\" = \"\";\n    \"thumbnail_profile_pic\" = \"\";\n    \"user_id\" = 2;\n})"
)
Run Code Online (Sandbox Code Playgroud)

但是(null)obj.id的"new"返回NSLog并返回以下内容@"query records":

(
    "<User: 0xa2b08a0> (entity: User; id: 0x95aebe0 <x-coredata:///User/tBFCC6C5F-7D2C-4AA0-BA96-B806EE360A762> ; data: <fault>)",
    "<User: 0xa2b0910> (entity: User; id: 0xa4b9780 <x-coredata:///User/tBFCC6C5F-7D2C-4AA0-BA96-B806EE360A763> ; data: <fault>)"
)
Run Code Online (Sandbox Code Playgroud)

Mun*_*ndi 13

从您的代码和注释看来,您似乎没有保存主上下文.一定要打电话

[managedObjectContext save:&error]; 
Run Code Online (Sandbox Code Playgroud)

在保存数据的所有子上下文中,以及主上下文之后的所有子上下文中.


pau*_*est 10

我刚刚完成了针对基本相同的问题.UITableViewController从NSManagedObjectContext中获取NSManagedObject的子类,检查属性是否为nil,如果已下载数据,则设置该属性,然后保存NSManagedObjectContext.像这样的东西:

MyManagedObject *mgObject = //get object from NSFetchResultsController
NSManagedObjectContext *mgObContext = mgObject.managedObjectContext;
if (!mgObject.data)
{
    mgObject.data = [NSData dataWithContentsOfURL:urlWithData];
    [mgObContext performBlock ^{
        NSError *saveError = nil;
        BOOL saveResult = [mgObContext save:&saveError];
        if (saveError || !saveResult)
        {
            NSLog(@"Save not successful..");
        }
    }];
}
//do something with myObject.data
Run Code Online (Sandbox Code Playgroud)

save函数给出了一个YES布尔返回值,saveError仍然是nil,但如果我退出应用程序并重新启动,当我的Core Data加载我的NSManagedObject子类时,data属性为nil,当这个UITableViewController重新启动时,它有再次下载数据.

我无法在任何地方找到解决方案......阅读Core Data文档并没有帮助.当我考虑上面的代码和我的代码之间的区别时,解决方案来找我,这些代码在NSManagedObject子类的工厂方法中设置属性,基本上是:

MyManagedObject *mgObject = [NSEntityForDescription insertNewObjectForEntityName:@"MyManagedObject" inManagedContext:mgObContext];
mgObject.attribute1 = some value
mgObject.attribute2 = another value
Run Code Online (Sandbox Code Playgroud)

唯一的区别是我从[mgObContext performBlock:]内部调用工厂方法.

所以修改后的代码是:

MyManagedObject *mgObject = //get object from NSFetchResultsController
NSManagedObjectContext *mgObContext = mgObject.managedObjectContext;
if (!mgObject.data)
{
    [mgObContext performBlock: ^{
        mgObject.data = [NSData dataWithContentsOfURL:urlWithData];
        NSError *saveError = nil;
        BOOL saveResult = [mgObContext save:&saveError];
        if (saveError || !saveResult)
        {
            NSLog(@"Save not successful..");
        }
    }];
}
//do something with myObject.data
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是完美的.所以我认为只要你修改了NSManagedObjects的属性,就需要在它们的NSManagedObjectContext的线程上这样做.


Mar*_*cel 5

想想我也会给可能有类似问题的人添加一些输入.

根据我的经验,尝试保存没有填充足够字段的对象在保存时似乎不会持续存在,并且在这种情况下似乎不会抛出任何错误.在保存火灾之前,请务必仔细检查您的字段是否按预期填写.

查看这些类型问题的另一种方法是解决问题.也许对象实际上是保存的,但是你确认它们实际上已经被保存的方法是错误的.通常,您可以通过使用特定条件查询CoreData获取记录来执行此操作.仔细检查您的条件是否正确,以及您的查询实际上是否返回了您的期望.

如果它没有返回您的预期,可能是由于您自己的错误,但也可能是存储结果的数组没有正确存储它们.在我不得不重命名之前我遇到了NSArray一些情况,因为有关数组名称的某些内容导致了引用问题,因此数组无法指向我期望的结果.干杯.