【问题标题】:UITableView Core Data reorderingUITableView 核心数据重新排序
【发布时间】:2011-01-22 14:06:32
【问题描述】:

我知道之前有人问过这个问题,我看了一下this question的答案。但是,我仍然对如何在 Core Data 项目中使用 UITableView 实现重新排序感到困惑。我所知道的是我需要在我的实体中有一个“displayOrder”属性来跟踪项目的顺序,并且我需要枚举获取结果中的所有对象并设置它们的 displayOrder 属性。

在我链接到的问题的给定代码中,表格视图委托方法调用了类似[self FF_fetchResults]; 这样的方法,并且没有给出该方法的代码,因此很难说出它到底是什么。

是否有任何示例代码可以证明这一点?这比共享大量代码更容易查看。

谢谢

【问题讨论】:

  • 你试过链接代码吗?如果您使用的是获取的结果控制器,您可能不需要做任何事情。该方法只是再次获取对象(现在排序已更改)。
  • 谢谢,我试试。订单改变后是否需要重新获取对象?
  • 如果您使用的是获取的结果控制器(并且当获取的结果控制器发生更改时有样板代码来更新表视图),则不需要这样做。
  • 我刚刚意识到链接代码似乎没有使用NSManagedObjectContextNSFetchedResultsController(据我所知)。我尝试通过使用NSManagedObject 而不是FFObject 并在最后保存上下文来适应我的需要。但这根本不起作用,当我移动一行时,用户界面完全混乱(行消失,其他人切换位置,只是整体混乱)。有没有实现这个的示例项目/开源项目?

标签: iphone objective-c cocoa-touch uitableview core-data


【解决方案1】:

我不确定您在哪个部分遇到了问题(基于 cmets)...但这是我的建议。 displayOrder 只是 NSManagedObject 类的一个简单属性。如果您可以保存托管对象,那么您将能够完成此功能。让我们先来看一个简单的 NSManagedObject:

@interface RowObj :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString *rowDescription;
@property (nonatomic, retain) NSNumber *displayOrder;

接下来,我们需要在 tableview 中显示数据的本地副本。我已经阅读了您制作的 cmets,但我不确定您是否正在使用 FetchedResultsController。我的建议是从简单的开始,只需使用普通的 tableviewcontroller 来更新行数据,只要用户更改显示顺序......然后在用户完成编辑时保存顺序。

tableviewcontoller 的界面如下所示:

@interface MyTableViewController : UITableViewController {
    NSMutableArray *myTableViewData;
}

@property(nonatomic,retain) NSMutableArray *myTableViewData;

@end 

接下来,我们需要在 viewWillAppear 方法中加载表格视图数据:

- (void)viewWillAppear:(BOOL)animated {
    myTableViewData = [helper getRowObjects]; // insert method call here to get the data
    self.navigationItem.leftBarButtonItem = [self editButtonItem];
}

这里发生了两件事……(稍后我会解释editButtonItem)第一件事是我们需要从CoreData 中获取我们的数据。当我必须这样做时,我有某种帮手(称它为你想要的)对象来完成这项工作。典型的 find 方法如下所示:

- (NSMutableArray*) getRowObjects{
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"RowObj" inManagedObjectContext:[self managedObjectContext]];
    [request setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayOrder" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    [sortDescriptors release];
    [sortDescriptor release];

    NSError *error;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (mutableFetchResults == nil) {
        // Handle the error.
    }
    [request release];
    return mutableFetchResults;
}

现在您有了数据,现在可以等待用户编辑表格。这就是 [self editButtonItem] 发挥作用的地方。这是一个内置功能,它返回一个栏按钮项目,该项目在编辑和完成之间切换其标题和关联状态。当用户点击该按钮时,它将调用 setEditing:animated: 方法:

要更新显示顺序,您需要覆盖 UITableViewController 类的 setEditing 方法。它应该看起来像这样:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [myTableView setEditing:editing animated:animated];
    if(!editing) {
        int i = 0;
        for(RowObj *row in myTableViewData) {
            row.displayOrder = [NSNumber numberWithInt:i++];
        }
        [helper saveManagedObjectContext]; // basically calls [managedObjectContext save:&error];
    }
}

当用户处于编辑模式时,我们不需要做任何事情......我们只想在他们按下“完成”按钮后保存。当用户在表格中拖动一行时,您可以通过覆盖 canMoveRowAtIndexPath 和 moveRowAtIndexPath 方法来更新显示顺序:

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    return true;
}

(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {

    RowObj *row = [myTableViewData objectAtIndex:sourceIndexPath.row];
    [myTableViewData removeObjectAtIndex:sourceIndexPath.row];
    [myTableViewData insertObject:row atIndex:destinationIndexPath.row];
}

再一次,我不在这里更新 displayOrder 值的原因是因为用户仍处于编辑模式...我们不知道用户是否已完成编辑,他们甚至可以取消他们所做的没有点击“完成”按钮。

编辑

如果您想删除一行,您需要覆盖 tableView:commitEditingStyle:forRowAtIndexPath 并执行以下操作:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the managed object at the given index path.
        RowObj *row = [myTableViewData objectAtIndex:indexPath.row];
        [helper deleteRow:row];

        // Update the array and table view.
        [myTableViewData removeObjectAtIndex:indexPath.row];
        [myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
    }   
}

【讨论】:

  • 感谢详细解答,我试试看。
  • 当然,如果您有任何问题,请告诉我...这基本上是我的一个应用程序的工作实现中的 word-4-word,因此它应该可以帮助您完成它。
  • 删除行怎么样?有什么特别需要做的吗?
  • 在答案中添加了删除...很高兴它对您有用!祝你好运
  • 当你显示行时,你是在引用 NSMutableArray 还是 NSFetchedResultsController 中的托管对象?整个控制器的完整示例将非常有用!非常感谢到目前为止的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2012-04-10
  • 1970-01-01
  • 2014-08-20
  • 2012-09-15
相关资源
最近更新 更多