首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何实现CoreData记录的重新排序?

如何实现CoreData记录的重新排序?
EN

Stack Overflow用户
提问于 2009-07-03 02:38:03
回答 9查看 22.8K关注 0票数 69

我在我的iPhone应用中使用了CoreData,但是CoreData没有提供一种自动的方式来允许你对记录进行重新排序。我想使用另一个列来存储订单信息,但是使用连续的数字作为排序索引有一个问题。如果我要处理大量数据,重新排序一条记录可能会涉及到更新排序信息中的许多记录(这有点像更改数组元素的顺序)

实现有效排序方案的最佳方式是什么?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2010-01-06 21:09:31

FetchedResultsController及其委托不能用于用户驱动的模型更改。参见the Apple reference doc。寻找用户驱动的更新部分。所以,如果你在寻找一些神奇的,一行的方法,遗憾的是,没有这样的方法。

您需要做的是在此方法中进行更新:

代码语言:javascript
复制
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
 userDrivenDataModelChange = YES;

 ...[UPDATE THE MODEL then SAVE CONTEXT]...

 userDrivenDataModelChange = NO;
}

还可以阻止通知做任何事情,因为用户已经做了更改:

代码语言:javascript
复制
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
 if (userDrivenDataModelChange) return;
 ...
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
 if (userDrivenDataModelChange) return;
 ...
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
 if (userDrivenDataModelChange) return;
 ...
}

我刚刚在我的待办事项应用程序(Quickie)中实现了这一点,它工作得很好。

票数 93
EN

Stack Overflow用户

发布于 2013-03-26 06:18:29

下面是一个快速示例,展示了将获取的结果转储到NSMutableArray中的方法,您可以使用它来移动单元格。然后,您只需更新名为orderInTable的实体上的属性,然后保存托管对象上下文。

这样,您就不必担心手动更改索引,而是让NSMutableArray为您处理。

创建一个可以用来暂时绕过NSFetchedResultsControllerDelegate的BOOL

代码语言:javascript
复制
@interface PlaylistViewController ()
{
    BOOL changingPlaylistOrder;
}
@end

表视图委托方法:

代码语言:javascript
复制
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    // Refer to https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40008228-CH1-SW14

    // Bypass the delegates temporarily
    changingPlaylistOrder = YES;

    // Get a handle to the playlist we're moving
    NSMutableArray *sortedPlaylists = [NSMutableArray arrayWithArray:[self.fetchedResultsController fetchedObjects]];

    // Get a handle to the call we're moving
    Playlist *playlistWeAreMoving = [sortedPlaylists objectAtIndex:sourceIndexPath.row];

    // Remove the call from it's current position
    [sortedPlaylists removeObjectAtIndex:sourceIndexPath.row];

    // Insert it at it's new position
    [sortedPlaylists insertObject:playlistWeAreMoving atIndex:destinationIndexPath.row];

    // Update the order of them all according to their index in the mutable array
    [sortedPlaylists enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        Playlist *zePlaylist = (Playlist *)obj;
        zePlaylist.orderInTable = [NSNumber numberWithInt:idx];
    }];

    // Save the managed object context
    [commonContext save];

    // Allow the delegates to work now
    changingPlaylistOrder = NO;
}

您的代理现在应该如下所示:

代码语言:javascript
复制
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    if (changingPlaylistOrder) return;

    switch(type)
    {
        case NSFetchedResultsChangeMove:
            [self configureCell:(PlaylistCell *)[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    if (changingPlaylistOrder) return;

    [self.tableView reloadData];
}
票数 16
EN

Stack Overflow用户

发布于 2009-12-19 11:28:04

迟来的回复:也许您可以将排序关键字存储为字符串。在两个现有行之间插入记录可以通过向字符串添加额外的字符来简单地完成,例如在行"A“和"B”之间插入"AM“。不需要重新排序。一个类似的想法可以通过在4字节整数上使用浮点数或一些简单的位运算来实现:插入一个排序键值位于相邻行中间的行。

当字符串太长,浮点数太小,或者int中没有更多空间时,可能会出现病理性的情况,但随后您可以对实体重新编号并重新开始。在罕见的情况下扫描和更新所有记录要比每次用户重新排序时都让每个对象出错要好得多。

例如,考虑int32。使用最高的3个字节作为初始排序提供了近1700万行,并且能够在任意两行之间插入最多256行。2字节允许在重新扫描之前在任意两行之间插入65000行。

下面是我想要的2字节增量和2字节插入的伪代码:

代码语言:javascript
复制
AppendRow:item
    item.sortKey = tail.sortKey + 0x10000

InsertRow:item betweenRow:a andNextRow:b
    item.sortKey = a.sortKey + (b.sortKey - a.sortKey) >> 1

通常情况下,调用AppendRow会产生sortKeys为0x10000、0x20000、0x30000等的行。有时,您必须在第一行和第二行之间执行InsertRow操作,从而导致sortKey为0x180000。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1077568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档