SwitUI实现Core Data动态查询
SwitUI实现Core Data动态查询

SwitUI实现Core Data动态查询

前提描述

在 SwiftUI 中使用 @FetchRequest 时,它的查询条件(如 predicate)在初始化后是不可变的。

例如,我们想要通过修改stockMarket变量,使用@FetchRequest动态查询Core Data数据:

// 当前股市指数
@State private var stockMarket:String = "GSPC"

@FetchRequest(
    fetchRequest: {
        let request = NSFetchRequest<Yahoo>(entityName: "Yahoo")
        // 筛选 Yahoo 中黄金的数据
        request.predicate = NSPredicate(format: "symbol == %@", stockMarket)    // stockMarket为变量
        request.sortDescriptors = [NSSortDescriptor(key: "updateTime", ascending: false)]
        return request
    }()
) var stockMarkets: FetchedResults<Yahoo>

实际上会报错:

Cannot use instance member 'stockMarket' within property initializer; property initializers run before 'self' is available

这表示无法在@FetchRequest时使用stockMarket变量。

目前 FetchRequest 是静态写死的,NSPredicate只能绑定静态变量:

predicate: NSPredicate(format: "symbol == %@", "GSPC")

如果想要根据变量的数值切换不同的查询条件,就需要将NSFetchRequest封装到方法中实现动态查询。

Core Data动态查询

因为@FetchRequest无法绑定动态变量,因此,我们可以尝试将变量封装到方法中,通过方法获取Core Data对象数组。每次修改变量时,重新调用一遍方法,就可以实现Core Data动态查询功能。

1、创建变量数组

@State private var stockMarkets: [Yahoo] = []

在SwiftUI中,创建一个用于存储的对象数组,不使用 @FetchRequest 查询对象数组。

2、创建查询方法

// 当前股市指数
@State private var stockMarket:String = "GSPC" 

func fetchData() {
    let request: NSFetchRequest<Yahoo> = Yahoo.fetchRequest()
    request.predicate = NSPredicate(format: "symbol == %@", stockMarket)
    request.sortDescriptors = [NSSortDescriptor(key: "updateTime", ascending: false)]
    do {
        stockMarkets = try viewContext.fetch(request)
    } catch {
        print("❌ Fetch failed: \(error)")
    }
}

这里的fetchData是一个自己封装的方法,没有使用@FetchRequest,是因为@FetchRequest是静态的,不能接受@State动态更新的predicate。

将NSFetchRequest封装在方法中,每次都会调用NSPredicate(format: “symbol == %@”, stockMarket) 动态构造查询条件。

然后通过 viewContext.fetch(request) 执行查询;

查询结果存到自定义的stockMarkets变量数组里。

这样就实现了“动态查询”:每次stockMarket改变,就重新fetch一次新的数据。

3、动态变量改变时重新调用查询方法

@State private var stockMarket: String = "GSPC" {
    didSet {
        fetchData()
    }
}

设置didSet方法,每次修改stockMarket变量时,都会重新调用查询方法。

实现效果

每次修改stockMarket变量,都会重新调用fetchData方法,从而实现动态查询。

本文的代码可以从GitHub的股票指数页面中查看:https://github.com/fangjunyu1/ERdepot/blob/main/ERdepot/View/StockIndexView.swift

总结

通过@State存储查询条件 + 自定义 fetchData() + 动态调用 fetch,可以实现Core Data的动态查询逻辑。

相关文章

1、Apple Core Data持久化框架:https://fangjunyu.com/2025/03/30/apple-coredata%e6%8c%81%e4%b9%85%e5%8c%96%e6%a1%86%e6%9e%b6/

2、SwiftUI获取Core Data数据的@FetchRequest:https://fangjunyu.com/2025/03/30/swiftui%e8%8e%b7%e5%8f%96core-data%e6%95%b0%e6%8d%ae%e7%9a%84fetchrequest/

3、Swift UI利用@Query动态切换排序:https://fangjunyu.com/2024/11/08/swift-ui%e5%88%a9%e7%94%a8query%e5%8a%a8%e6%80%81%e5%88%87%e6%8d%a2%e6%8e%92%e5%ba%8f/

4、SwiftUI @Query动态排序扩展篇:传递绑定变量:https://fangjunyu.com/2024/12/12/swiftui-query%e5%8a%a8%e6%80%81%e6%8e%92%e5%ba%8f%e6%89%a9%e5%b1%95%e7%af%87%ef%bc%9a%e4%bc%a0%e9%80%92%e7%bb%91%e5%ae%9a%e5%8f%98%e9%87%8f/

   

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开发者。

欢迎加入我们的 微信交流群QQ交流群,交流更多精彩内容!
微信交流群二维码 QQ交流群二维码

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注