deleteObject删除但在sqlite3数据库中留下空行?

时间:2011-09-24 19:09:00

标签: objective-c object core-data sqlite managed

我需要删除updatePick中显示的数据库的选定行,但似乎无法使managedObject行中的[context deleteObject:managedObject];行正确无误。这是deleteUpdate方法:

-(void)deleteUpdate {
    NSLog(@"35-Delete pressed.");
    NSManagedObjectContext *context = [self managedObjectContext];
    NSEntityDescription *updateEntity = [NSEntityDescription entityForName:@"Updates" inManagedObjectContext:context];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:updateEntity];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(dateGains = %@)", [arrayNSDateGains objectAtIndex:updatePick]];
    [fetchRequest setPredicate:predicate];

    NSArray *gains = [context executeFetchRequest:fetchRequest error:nil];

    for (updateGains in gains) {
        [context deleteObject:updateGains];
    }
    [self saveContext];
}

这设法删除数据库中行的内容(YEAH),除了它留下一个空行和三个剩余元素:主键(Z_PK)和两个整数(Z_ENT)& (Z_OPT)。空行会在其他地方导致错误。我在这里缺少什么?

2 个答案:

答案 0 :(得分:3)

核心数据经常在删除后在sqlite存储中留下空行。文档明确指出存储文件在删除之后不会变小,直到持久存储对象决定压缩存储的某个任意点。

一般来说,查看sqlite商店本身就是浪费时间。核心数据不是SQL。实体不是表格。对象不是行。属性不是列。关系不是联接。核心数据是一个对象图管理系统,可能会或可能不会持久保存对象图,并且可能会或可能不会使用远远落后的SQL来执行此操作。试图用SQL术语来思考核心数据将导致你完全误解核心数据并导致更多的悲伤和浪费时间。

Core Data只能选择将对象序列化(冻干)到sqlite存储中。但是,如何做到这一点没有记录,因此直接查看sqlite商店不会告诉你太多。

确认对象已被删除的唯一方法是获取并保存其透明度managedObjectID。删除后,请求persistentStoreCoordinator使用objectWithID:获取id的对象。如果该对象已被删除,则无法找到它。

删除后只有几种方法可以保留对象。撤消管理器可以回滚 明显的 删除,但这不是这种情况。如果在其他地方保留托管对象,则删除后内存中的对象将保留(尽管它不会像获取那样显示在Core Data操作中。)

我怀疑您遇到的任何问题是由商店的问题引起的。这些问题非常罕见。

更新

  

保存后,我做了[self setNeedsDisplay];触发一个   根据数据库中的数据重新绘制条形图。该   第一个可变数组尝试insertObject:atIndex:一个nil对象   导致崩溃......    我插入了一个if(dateGained == nil)继续;在那里   发生了下一个错误,效果很好。

您的问题是,在上下文删除其中一些后,您的UI控制器不会更新其托管对象的计数。

例如:您有一个表格,每行显示一个Update个对象。在开始时,UI控制器将获取所有现有的Update个对象。它告诉表格它有[fetchObjects count]。然后你删除了一些Update对象,但是你现在没有告诉它它有更少的行。该表将尝试访问数组中超过导致崩溃的最后一个元素的对象。

这里的解决方案是注册您的控制器以获取上下文的通知:

NSManagedObjectContextObjectsDidChangeNotification

...然后在调用[self setNeedsDisplay]之前更新数组和表行数。然后表将了解它应该有多少行。

任何依赖于获取对象计数的UI元素都需要与对象图中的更改保持同步,尤其是删除。

答案 1 :(得分:0)

你忘了取实体了。这样做:

NSArray *results = [context executeFetchRequest:request error:nil];
if (results) {
   for (NSManagedObject *updateGains in results) {
      [context deleteObject:updateGains];
   }
[context save:nil];
}

[self saveContext];