能否用swift-collections的OrderedSet表示CoreData一对多关系?
能不能用Swift Collections的OrderedSet替换CoreData里的NSOrderedSet?
直接替换会编译失败,具体问题如下:
原可正常运行的代码
@objc(Ingredient) class Ingredient: Entity { @NSManaged var recipes: NSOrderedSet }
修改后编译报错的代码
import OrderedCollections class Ingredient: Entity { @NSManaged var recipes: OrderedSet<Recipe> }
报错信息:
error build: Property cannot be marked @NSManaged because its type cannot be represented in Objective-C
原因
@NSManaged标记的属性必须能被Objective-C识别——CoreData底层基于Objective-C运行时实现,而Swift Collections的OrderedSet是纯Swift编写的结构体,没有做Objective-C桥接支持,所以CoreData无法直接识别它作为托管属性的类型。
解决方案
用计算属性做一层封装,内部仍用NSOrderedSet满足CoreData的要求,对外暴露OrderedSet<Recipe>的友好接口:
import OrderedCollections @objc(Ingredient) class Ingredient: Entity { // 内部存储用NSOrderedSet,保留@NSManaged标记 @NSManaged private var _recipes: NSOrderedSet // 对外提供OrderedSet的访问接口 var recipes: OrderedSet<Recipe> { get { // 将NSOrderedSet转换为OrderedSet OrderedSet(_recipes.compactMap { $0 as? Recipe }) } set { // 将新的OrderedSet转换为NSOrderedSet存回CoreData _recipes = NSOrderedSet(array: newValue.elements) } } }
注意事项
- 每次读写都会触发类型转换,数据量较大时可能存在性能损耗,需根据业务场景评估
- 如果需要监听集合变化,要确保setter能正确触发CoreData的变更通知
内容的提问来源于stack exchange,提问作者Alex Dong
相关产品推荐
相关产品推荐

