核心数据TableView - 编辑模式下的多个选择

时间:2015-01-22 06:04:51

标签: objective-c uitableview core-data delete-row multipleselection

我有两个使用Core Data的TableView。我有一个ItemTableview,用户列出了多行Item,它允许在编辑模式下进行多项选择。在编辑模式下,它允许用户删除所选项目,或一次删除所有项目。我希望将已删除的项目添加到TrashTableView。

这是我到目前为止所拥有的:

    - (IBAction)deleteAction:(id)sender
{

    NSManagedObjectContext *context = [self managedObjectContext];

    NSArray *selectedRows = [self.tableView indexPathsForSelectedRows];
    BOOL noItemsAreSelected = selectedRows.count == 0;
    BOOL deleteSpecificRows = selectedRows.count > 0;

    if (noItemsAreSelected) {

        // Delete all objects from the Core Data.
        NSFetchRequest *allItems = [[NSFetchRequest alloc] init];
        [allItems setEntity:[NSEntityDescription entityForName:@"Item" inManagedObjectContext:context]];
        [allItems setIncludesPropertyValues:NO];

        NSError *error = nil;
        NSArray *items = [context executeFetchRequest:allItems error:&error];

        for (NSManagedObject *object in items) {
            [context deleteObject:object];
        }
        // Add to Trash
        for (NSManagedObject *trashObject in items) {

        Item *selectedItems = trashObject; <-- #warning -Incompatible pointer types initializing "Items" with an expression of type "NSManagedObject"-
        Trash *newTrash = [NSEntityDescription insertNewObjectForEntityForName:@"Trash" inManagedObjectContext:context];

        newTrash.trashname = selectedItems.itemname;
        newTrash.created = [NSDate date];

        // Save the context
        NSError *saveError = nil;
        if (![context save:&saveError]) {
            NSLog(@"Save Failed! %@ %@", saveError, [saveError localizedDescription]);
        }
        }

        // Delete from the Array
        [_item removeAllObjects];

        // Tell the tableView that we deleted the objects.
        [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

        [self.tableView setEditing:NO animated:YES];
    }

    else if (deleteSpecificRows) {

            NSMutableIndexSet *indicesOfItemsToDelete = [NSMutableIndexSet new];
            for (NSIndexPath *selectionIndex in selectedRows)
            {
                [indicesOfItemsToDelete addIndex:selectionIndex.row];
            }
            // Delete from the Array
            [_item removeObjectsAtIndexes:indicesOfItemsToDelete];

            // Tell the tableView that we deleted the objects
            [self.tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];

        [self.tableView setEditing:NO animated:YES];
    }
}

调用if (noItemsAreSelected)时,会删除所有项目,并将它们全部添加到TrashTableView中,但只有ItemTableView的第一行才会显示字符串。所以在TrashTableView中,第一行有一个文本,但其余行只是没有任何文本的空白单元格。 在调试器中,空白单元格具有NSString trashname = nil;但NSDate created = "2015-01-22 03:41:30 +0000";具有日期。

对于else if (deleteSpecificRows)我不知道如何在核心数据中执行此操作....

我花了很多时间安静地试图解决这个问题,所以任何帮助都会非常感激。谢谢!

1 个答案:

答案 0 :(得分:1)

您正在以错误的顺序执行操作:您当前从上下文中删除所有项目,然后遍历这些项目,创建相应的垃圾项目并每次保存上下文。这适用于第一项。但是在第一个项目之后,上下文已经被保存,因此将发生删除操作(对于所有项目),这将删除所有属性。因此你的空值。

我会按如下方式对其进行重组:

if (noItemsAreSelected) {

    NSFetchRequest *allItems = [[NSFetchRequest alloc] init];
    [allItems setEntity:[NSEntityDescription entityForName:@"Item" inManagedObjectContext:context]];
    [allItems setIncludesPropertyValues:NO];

    NSError *error = nil;
    NSArray *items = [context executeFetchRequest:allItems error:&error];

    for (Item *trashObject in items) {
    // Add to Trash
        Trash *newTrash = [NSEntityDescription insertNewObjectForEntityForName:@"Trash" inManagedObjectContext:context];

        newTrash.trashname = trashObject.itemname;
        newTrash.created = [NSDate date];
        // Delete
        [context deleteObject:trashObject];
    }
    // Save the context
    NSError *saveError = nil;
    if (![context save:&saveError]) {
        NSLog(@"Save Failed! %@ %@", saveError, [saveError localizedDescription]);
    }

请注意,更改for(Item *trashObject ...)中的强制转换应该避免编译器警告。

修改

对于deleteSpecificRows情况,您可以使用类似的代码,但使用_item(我假设这是一个可变数组,它是tableView的数据源):

else if (deleteSpecificRows) {
    NSMutableIndexSet *indicesOfItemsToDelete = [NSMutableIndexSet new];
    for (NSIndexPath *selectionIndex in selectedRows)
    {
        // First, get the trash object...
        Item *trashObject = [_item objectAtIndex:selectionIndex.row];
        // Add to Trash
        Trash *newTrash = [NSEntityDescription insertNewObjectForEntityForName:@"Trash" inManagedObjectContext:context];
        newTrash.trashname = trashObject.itemname;
        newTrash.created = [NSDate date];
        // and delete the object from the context
        [context deleteObject:trashObject];
        // and update the list of items to delete
        [indicesOfItemsToDelete addIndex:selectionIndex.row];
    }
    // Delete from the Array
    [_item removeObjectsAtIndexes:indicesOfItemsToDelete];
    // Tell the tableView that we deleted the objects
    [self.tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView setEditing:NO animated:YES];
}

请注意,这是未经测试的,因此可能需要整理....

从长远来看,您可能需要考虑a)使用NSFetchedResultsController充当tableView的数据源,b)而不是为垃圾桶创建单独的实体,将标志添加到现有实体(inTrash? )并将其改为真。然后,您的tableView必须只显示inTrash = false的项目。