SwiftUI中使用FetchRequest时,如何保持NSOrderedSet的顺序?
CoreData有序一对多关系的顺序保持方案
关于排序描述符
不存在能直接对应NSOrderedSet内部维护顺序的排序描述符。CoreData的有序一对多关系是通过底层特殊存储逻辑(比如SQLite中的隐藏列)维护顺序,但FetchRequest不会自动识别这个顺序——你当前用空sortDescriptors时,查询结果的顺序由CoreData的默认存储策略决定,这就是添加后顺序混乱的原因;重启后看似恢复正常只是巧合,完全不可靠。
可靠的顺序保持方法
有两种可行方案:
直接访问Deck的有序集合属性
既然你已经获取到了指定的Deck实例,完全不需要单独用FetchRequest查询Flashcard。直接读取deck.flashcards(NSOrderedSet类型)并转成数组,就能得到用户设定的准确顺序,无论添加操作后还是重启应用,顺序都不会乱:guard let flashcards = deck.flashcards?.array as? [Flashcard] else { return } // 使用这个flashcards数组渲染视图这种方法最直接,完全利用CoreData有序关系的原生能力,不需要额外维护字段。
手动维护排序索引字段
如果必须用FetchRequest查询(比如有复杂过滤需求),可以给Flashcard实体添加一个orderIndex整数属性,手动维护顺序:- 添加新
Flashcard时,设置orderIndex为当前Deck下所有Flashcard的最大orderIndex值加1;如果是插入到指定位置,还要调整后续所有Flashcard的orderIndex(比如插入到位置2,把位置2及之后的项orderIndex加1) - 配置
FetchRequest的sortDescriptors:@FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \Flashcard.orderIndex, ascending: true)], predicate: NSPredicate(format: "deck == %@", deck) ) var flashcards: FetchedResults<Flashcard> - 当用户调整卡片顺序时(比如拖动排序),同步更新所有受影响卡片的
orderIndex值,并保存上下文。
- 添加新
内容的提问来源于stack exchange,提问作者krawieck
相关产品推荐
相关产品推荐

