【问题标题】:Core Data ordering with a UITableView and NSOrderedSet使用 UITableView 和 NSOrderedSet 对核心数据进行排序
【发布时间】:2012-04-10 03:49:09
【问题描述】:

在使用 Core Data 作为后备存储的 UITableViewController 中实现用户定义的排序需要执行哪些步骤?

我还需要回复-tableView:moveRowAtIndexPath:fromIndexPath:toIndexPath: 还是表格视图自动处理模型重新排序?我可以只选中 Core Data 模型文件中的“Ordered”复选框并期望它将更改从 table view 传输到 store,还是我必须做更多?我是否必须改变我的fetchedResultsController 获取它的对象的方式(例如,添加一个排序描述符)?

【问题讨论】:

    标签: ios uitableview core-data ios5 nsorderedset


    【解决方案1】:

    你不需要放弃 NSFetchedResultsController 或 NSOrderedSet。如果您坚持使用 NSOrderedSet,那么简单的方法就是向您的对象 NSManagedObject 子类添加一个方法。因此,例如,如果您有一个包含有序章节集的对象 Book,您可以向章节对象添加一个方法:

    - (NSUInteger)indexInBookChapters
    {
        NSUInteger index = [self.book.chapters indexOfObject:self];
        return index;
    }
    

    提示:将此添加到一个类别中,这样它就不会被 CoreData 自动生成的代码覆盖。

    然后你可以在你的 NSFetchedResultsController 的排序描述符中使用这个方法:

    fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"indexInBookChapters" ascending:YES]];
    

    【讨论】:

    • 你是说它是一个糟糕的解决方案,因为它不适用于一些罕见的场景吗?如果我要对有序多对多关系的罕见场景建模,我可能只使用第三个对象,比如 BookChapterPair,然后我会在那里添加索引属性。所以我可以通过 bookChapterPair.indexInBook 或 bookChapterPair.indexInChapter 获取索引。然后只需设置 NSFetchedResultsController 来获取 BookChapterPair 实体而不是 Chapter 或 Book。简单!
    • 实际上,在 Apple 关于 Core Data 多对多关系的文档中,他们为许多场景推荐了第三个对象,甚至说“中间实体的一个优点是您还可以使用它来添加更多信息到关系——例如,“FriendInfo”实体可能包含一些带有“排名”属性的友谊强度指示。”在我们的例子中,额外的信息将是索引。顺便说一句,我只说它很少见,因为虽然我遇到了多对多关系的许多用途,但我从未遇到过需要订购的关系。你有吗?
    • 在 iOS 5 在 Core Data 中引入有序关系之前,Apple 的文档会提到唯一可能的解决方案是有道理的。但我现在发现将第三个对象添加到数据模型中只是为了保持顺序是多余的。因为这个问题是关于 NSOrderedSet 的,所以我还假设提问者想学习使用有序关系
    • 您应该自己阅读文档:developer.apple.com/library/mac/documentation/Cocoa/Conceptual/… 它与订购的多对多无关,一般来说只是多对多。 IE。即使在使用 NSSet 时,您仍然经常需要第三个中间对象。
    • @RichardVenable 你试过了吗?如果您使用 SQLite 存储,NSFetchedResultsController 将无法使用此类排序描述符。
    【解决方案2】:

    这里的最佳做法是不要使用fetchedResultsController,因为它需要一个排序描述符,正如您所提到的。您可以使用虚拟属性,但这显然不是一个好习惯。相反,在tableView:cellForRowAtIndexPath: 中使用objectAtIndex 并在需要时重新加载表数据,也许使用Key-Value Observing,但根据您的用例,可能会有更简单且不易崩溃的方法。

    是的,你必须实现tableView:moveRowAtIndexPath:fromIndexPath:toIndexPath:

    另见

    NSFetchedResultsController and NSOrderedSet relationships

    【讨论】:

      【解决方案3】:

      我有一个 Core Data 实体的属性,假设它是一个名为 sortOrderNSNumber

      当您在此列表中初始化一个新对象时,按升序分配sortOrder,以便默认排序顺序存在。

      最后,告诉您的 fetchedResultsController 为这个 sortOrder 属性使用额外的 sortDescriptor

      当用户调整条目的位置时,您可以将sortOrder设置为条目前后的平均值。

      (只是一个想法 --- 我还没有处理过这个问题或必须实施它,但正在为我的项目考虑它。)

      【讨论】:

      • 感谢您的回答,但这是我想要避免的。据说,iOS 5 中 Core Data 中的新 API 会自动为您进行排序。实现起来有点棘手,尤其是在重新排序时。
      • 不错!一旦得到一个好的答案,我将不得不检查这个问题:)
      • 另外:显然 iCloud 不支持有序数据;如果你正在与 iCloud 同步,那么你就不走运了:“当与 iCloud 一起使用时,此时 SQLite 存储有几个限制:不支持有序关系。” developer.apple.com/library/ios/#releasenotes/DataManagement/…
      • 是的,我今天也看到了。我完全不明白为什么订购与 iCloud 不兼容,但我会说它会在未来出现。数据迁移的限制大概是一样的。
      • 核心数据不支持将排序+显示映射到开箱即用的tableviews和collectionviews上,这实际上是令人难以置信的蹩脚!
      猜你喜欢
      • 2013-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多