Core Data TableView - 编辑模式下的多项选择
Core Data TableView - Multiple Selection During Edit Mode
我有两个使用 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)
我不知道如何在核心数据中做到这一点....
我花了很多时间试图解决这个问题,因此非常感谢您的帮助。谢谢!
您的操作顺序错误:您目前从上下文中删除了所有项目,然后遍历这些项目,每次都创建相应的垃圾项目并保存上下文。这对第一项有效。但是在第一个项目之后,上下文已经被保存,所以删除操作(对于所有项目)将会发生,这会消除它们的所有属性。因此你的空值。
我会按如下方式重组它:
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
?) 并将其更改为 true。然后,您的 tableView 将不得不仅显示带有 inTrash = false 的项目。
我有两个使用 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)
我不知道如何在核心数据中做到这一点....
我花了很多时间试图解决这个问题,因此非常感谢您的帮助。谢谢!
您的操作顺序错误:您目前从上下文中删除了所有项目,然后遍历这些项目,每次都创建相应的垃圾项目并保存上下文。这对第一项有效。但是在第一个项目之后,上下文已经被保存,所以删除操作(对于所有项目)将会发生,这会消除它们的所有属性。因此你的空值。
我会按如下方式重组它:
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
?) 并将其更改为 true。然后,您的 tableView 将不得不仅显示带有 inTrash = false 的项目。