【问题标题】:iOS CoreData parsing from CSV cannot save error 1570 nil object从 CSV 解析 iOS CoreData 无法保存错误 1570 nil 对象
【发布时间】:2014-11-04 01:13:25
【问题描述】:

我对 Objective c 和 iOS 还很陌生,非常感谢这里的一些帮助。 我一直在用头撞墙试图让它工作,但不断收到错误:

Failed to save to data store: The operation couldn’t be completed. (Cocoa error 1570.)

我正在做的是导入 CSV 文件。

据我所知,它正在部分工作。 CSV 被正确解析,我得到了所有正确的值,并且我已经调试过了,据我所知,KA 对象都得到了正确的值。

但是我处理关系的方式似乎有问题 - 1570 问题来自一个 nil newTrainingDay 的必需日期字段(它似乎是从我调试时填充的)。我有一种感觉有其他问题,但我不确定是什么..

谁能告诉我我在这里做错了什么?

【问题讨论】:

  • 如果您在 newTrainingDay.date = date; 行之后立即检查 newTrainingDay.date被执行,它的价值在那个时候好吗?另外,同一个 NSManagedObject 中的其他字段呢?也就是说,如果您查看整个托管对象,所有字段似乎都已完成?
  • 是的,这是一个很好的价值,这是它的奇怪部分。当我执行newTrainingDay = day; 时,它似乎正在发生(我认为) - 因为错误不会在每个训练日的第一天(实际设置日期的那个)出现
  • 发生了另一件奇怪的事情 - 数据没有被设置,但我从视图控制器中的上下文显示,它显示,但只显示最后一天 - 但是有两天csv(每天都有多组,格式如帖子顶部)
  • 这看起来有可能吗(我并没有真正遵循您对违规代码上方的提取所做的事情)。 stackoverflow.com/questions/19666178/… 不过,这是有多个上下文在起作用的地方。
  • 嗯,这听起来很有趣,就像正在发生的事情一样。我没有使用多个上下文。

标签: ios objective-c core-data


【解决方案1】:

我认为问题源于创建新对象并将其插入数据库,然后再搜索以查看是否存在满足您需求的现有对象。以这段代码为例:

 // look for existing day
    KATrainingDay *newTrainingDay = [NSEntityDescription insertNewObjectForEntityForName:@"KATrainingDay" inManagedObjectContext:self.managedObjectContext];
    // Fetching
    fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"KATrainingDay"];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"date == %@", date]];
    // Execute Fetch Request
    fetchError = nil;
    NSArray *trainingDays = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
    // if you found it
    if (!fetchError) {
        if ([trainingDays count]) {
            for (KATrainingDay *day in trainingDays) {
                newTrainingDay = day;
            }
        } else {
            // set name and date for training day
            newTrainingDay.date = date;
            newTrainingDay.name = trainingDayNameString;
            [newTrainingDay addRoutinesObject:newTrainingRoutine];
            [newTrainingRoutine addTrainingDaysObject:newTrainingDay];
        }

您首先创建一个KATrainingDay 并将其插入到您的上下文中,然后进行提取以查找具有正确日期的KATrainingDay。如果找到它,则将指针 (newTrainingDay) 分配给刚刚获取的对象。 但是您刚刚插入的对象仍在上下文中(尽管您不再拥有指向它的指针)并且其所有属性和关系的值都为零。因此,当您保存时,该对象将失败所需的日期限制。

要解决此问题,请仅在您的 fetch 未找到匹配项时插入新对象:

 // look for existing day
    KATrainingDay *newTrainingDay;
    // Fetching
    fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"KATrainingDay"];
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"date == %@", date]];
    // Execute Fetch Request
    fetchError = nil;
    NSArray *trainingDays = [self.managedObjectContext executeFetchRequest:fetchRequest error:&fetchError];
    // if you found it
    if (!fetchError) {
        if ([trainingDays count]) {
            for (KATrainingDay *day in trainingDays) {
                newTrainingDay = day;
            }
        } else {
            // set name and date for training day
            newTrainingDay = [NSEntityDescription insertNewObjectForEntityForName:@"KATrainingDay" inManagedObjectContext:self.managedObjectContext]
            newTrainingDay.date = date;
            newTrainingDay.name = trainingDayNameString;
        } 
        [newTrainingDay addRoutinesObject:newTrainingRoutine];

(对于其他实体也是如此)。在上面,我还将addRoutinesObject: 调用移到了 else 块之外,因此无论您是找到现有的还是创建新的(我假设您想要),它都会执行。请注意,您不需要设置关系的两侧 - 如果您设置一侧,CoreData 会自动为您执行另一侧(假设它们被定义为反向)。另一个提示,你不需要你的 for 循环来获取数组中的最后一项,你可以使用:

newTrainingDay = [trainingDays lastObject];

【讨论】:

  • 漂亮。谢谢你抓住那个。我实际上尝试了一些类似的东西,但正在做KATrainingDay *newTrainingDay = [[KATrainingDay alloc] init];,而不是仅仅创建一个指向无处的指针。显然,这不适用于NSManagedObjects。是的,我想我可以使用firstObjectlastObject 而不是循环,因为每个提取中应该只有一个。好点子。谢谢!
猜你喜欢
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 2013-06-25
  • 2013-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多