SwiftUI中如何通过UserDefaults更新@ObservedResults过滤器并刷新
解决@ObservedResults不随UserDefaults更新的问题
问题原因
你当前的@ObservedResults查询条件是在视图初始化时一次性计算的,直接读取UserDefaults的初始值。当shareSelection通过@AppStorage修改后,这个查询闭包不会重新执行,因此查询结果不会更新。
解决方案
方案1:使用Realm的@Query(推荐,Realm Swift 10.20+版本支持)
@Query支持动态更新查询条件,适配@AppStorage的变化:
@AppStorage("shareSelection") var shareSelection = "BTCUSDT" @Query(coinModel.self) var coinsResult: [coinModel] var body: some View { Text(coinsResult.first?.s ?? "") .onChange(of: shareSelection) { newValue in // 当shareSelection变化时,更新查询谓词 _coinsResult = Query(filter: "s == %@", newValue) } } // 初始化时设置初始查询 init() { _coinsResult = Query(filter: "s == %@", shareSelection) }
方案2:通过ViewModel手动管理查询(兼容旧版本Realm)
如果你的Realm版本不支持@Query,可以用ObservableObject监听shareSelection变化,手动更新查询:
首先创建ViewModel:
import RealmSwift import SwiftUI class CoinViewModel: ObservableObject { @AppStorage("shareSelection") var shareSelection = "BTCUSDT" { didSet { updateQuery() } } @Published var coinsResult: Results<coinModel>! init() { updateQuery() } private func updateQuery() { guard let realm = try? Realm() else { return } coinsResult = realm.objects(coinModel.self).filter("s == %@", shareSelection) } }
然后在视图中使用:
@StateObject private var viewModel = CoinViewModel() var body: some View { Text(viewModel.coinsResult.first?.s ?? "") }
额外注意事项
- 避免直接使用
coinsResult[0],当查询结果为空时会触发崩溃,建议用coinsResult.first?.s ?? ""做安全处理。
内容的提问来源于stack exchange,提问作者Engin Çelik
相关产品推荐
相关产品推荐

