删除/删除Core Data中的记录的速度非常慢

时间:2012-01-07 19:59:55

标签: iphone cocoa-touch core-data

我正在对应用程序进行最后润色,并且难以批量删除记录。在一个按钮的命中一套约。需要将3500条记录添加到数据库中。这不是问题,需要大约。 3-4秒。

但有时(不常见,但选项需要在那里)所有这些记录都需要删除。我刚刚运行了这个操作,花了20分钟。这可能有什么问题?只有一个依赖项,所有记录都是特定Collection的子项。

我将所有项目添加到集合中,从集合中删除它们然后逐个删除。每5%我更新对话,当一切都完成后,我提交更改。但删除项目只需要很长时间(因为我可以看到进度对话进展非常缓慢)

- (void) deleteList:(DOCollection *) collection {

    // For the progress dialogue
    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObject:@"Clearing vocabulary list!" forKey:@"message"];
    float totalItems = [collection.items count];
    float progress = 0;
    float nextProgressRefresh = 0.05;         

    NSMutableSet* itemsSet = [NSMutableSet set];
    for (DOItem* item in collection.items) {
        [itemsSet addObject:(NSNumber*)[NSNumber numberWithInt:[item.itemId intValue]]];
    }

    // Remove all of them from the collection
    [managedObjectContext performBlockAndWait:^{
        [collection setItems:[NSSet set]];
    }];    

    for (NSNumber* itemId in itemsSet) {
        DOItem* item = [itemController findItem:[itemId intValue]];
        if (item != nil) {
           [[self itemController] removeItem:item];
        }

        progress++;
        if((nextProgressRefresh < (progress / totalItems))){  
            NSString* sProgress = [NSString stringWithFormat:@"%f", (progress / totalItems) * 0.85];
            //[dict setValue:@"Saving the database...!" forKey:@"message"];
            [dict setValue:sProgress forKey:@"progress"];
            [[NSNotificationCenter defaultCenter] postNotificationName:kUpdatePleaseWaitDialogue object:dict]; 
            nextProgressRefresh = nextProgressRefresh + 0.05;
        }        
    }

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [managedObjectContext performBlockAndWait:^{
            [[self collectionController] commitChanges];
        }];
        [[NSNotificationCenter defaultCenter] postNotificationName:kSavingDataComplete object:nil]; 
    });  

    //NSLog(@"Wait 2!");
    [NSThread sleepForTimeInterval:1];    

}
在DOItemController中

- (void) removeItem: (NSManagedObject*) item {
    [[self managedObjectContext] deleteObject:item];
}

1 个答案:

答案 0 :(得分:2)

不确定如何构建数据模型。但我会将其设置为级联删除对象。如果DOItem对象对于DOCollection是唯一的,则可以将删除规则设置为级联。这将自动删除关联的DOItem,并将其从DOCollection项目集对象中删除。

要从DOCollection中删除DOItem对象,请检查您的DOCollection.h文件,您应该有一个方法

-(void)removeDOItemObjects:(NSSet *)value

如果没有,它们仍可能由Core Data为您动态生成。在您的头文件中,您应该有以下内容:

@property(nonatomic,retain) DOItem *items

然后在你的实现文件中,你应该有以下几点:

@synthesize items

应自动为这些方法生成适当的方法:

-(void)addItemsObject:(DOItem*)value
-(void)addItems:(NSSet *)values
-(void)removeItemsObject:(DOItem *)value
-(void)removeItems:(DOItem *)values
-(NSSet *)items

请参阅“自定义多对多关系访问器方法”here for more info

在您创建数据模型和关联的实施文件时,将为您提供此方法,并且应由Core Data高度优化。然后,您需要做的就是删除对象:

- (void) deleteList:(DOCollection *) collection {

    // Remove all of them from the collection
    [managedObjectContext performBlockAndWait:^{
        // Updated 01/10/2012
        [collection removeItems:collection.items];
        NSError *error = nil;
        if (![managedObjectContext save:&error]) { 
           NSLog(@"Core Data: Error saving context."); }
       };
    }];

}

您可能希望使用此方法检查删除的效果,并继续向用户提供反馈。如果性能是一个问题,请考虑跨步,将设置划分为块并在每个步骤之前执行上述方法,更新用户界面等。

同样,我不确定您的应用程序架构,但乍一看,这看起来像是问题。

祝你好运!