SwiftData中FetchDescriptor的propertiesToFetch被忽略,返回完整模型
SwiftData中propertiesToFetch未限制返回属性的问题解决
你遇到的问题核心在于:propertiesToFetch默认不会改变返回结果的类型。它仅告诉SwiftData初始查询时优先加载指定属性,但返回的仍然是完整的Person托管对象。当你访问未被初始加载的属性(比如description里的age),SwiftData会自动触发按需加载(faulting),从数据库补全该属性的值,最终打印出包含所有属性的对象。
以下是两种可行的解决方法:
方法1:返回字典格式的部分属性
将FetchDescriptor的resultType设置为.fetchDictionary,查询结果会以字典数组形式返回,仅包含你指定的属性:
func fetch() { let container = try! ModelContainer(for: Person.self) do { let context = ModelContext(container) let person = Person(name: "Joe", age: 30) context.insert(person) try context.save() // 先保存数据到数据库 var fetch = FetchDescriptor<Person>(sortBy: [SortDescriptor(\.name, order: .reverse)]) fetch.propertiesToFetch = [\.name] fetch.resultType = .fetchDictionary // 指定返回字典类型 let people = try context.fetch(fetch) as! [[AnyHashable: Any]] if let personDict = people.first { print("Person name: \(personDict["name"]!)") // 输出:Person name: Joe } } catch { print("error: \(error)") } }
方法2:使用自定义投影结构体
定义一个仅包含目标属性的结构体,通过resultType指定返回该类型,实现类型安全的部分属性查询:
// 定义投影结构体,需符合Decodable struct PersonProjection: Decodable { let name: String } func fetch() { let container = try! ModelContainer(for: Person.self) do { let context = ModelContext(container) let person = Person(name: "Joe", age: 30) context.insert(person) try context.save() var fetch = FetchDescriptor<Person>(sortBy: [SortDescriptor(\.name, order: .reverse)]) fetch.propertiesToFetch = [\.name] fetch.resultType = .custom(PersonProjection.self) // 指定自定义投影类型 let people = try context.fetch(fetch) as! [PersonProjection] print(people) // 输出:[PersonProjection(name: "Joe")] } catch { print("error: \(error)") } }
补充说明
- 若坚持返回
Person实例,无法真正“隐藏”未指定的属性——因为Person是托管对象,只要上下文存在,访问未加载的属性就会自动触发按需加载。 - 测试时务必调用
context.save(),确保数据持久化,避免缓存导致的异常结果。
内容的提问来源于stack exchange,提问作者Dubon Ya'ar
相关产品推荐
相关产品推荐

