SwiftUI中含搜索与下拉刷新的视图在ObservableObject变更时故障
问题分析与解决
首先你的代码存在一处明显遗漏:MyView中没有声明Model的实例,需要添加@StateObject(iOS 14及以上,用于视图自身持有模型)或者@ObservedObject(如果模型从父视图传入),比如:
struct MyView: View { @State var text = "" @StateObject var model = Model() // 补上这行 // ... 其他代码不变 }
接下来是核心问题:当你在.refreshable闭包中同步更新@Published属性时,会立即触发视图重新渲染,而此时下拉刷新的UI动画还处于活跃状态,和searchable的状态更新产生冲突,导致搜索栏异常。你之前用DispatchQueue.main.async无效,是因为.refreshable闭包本身就在主线程执行,重复调度主线程不会改变执行时机。
解决方法
把更新操作放在异步任务中,让下拉刷新动画先完成再更新模型属性,有两种简单实现方式:
方式一:利用Task.yield()让出执行权
让系统先处理完刷新动画的UI更新,再执行模型属性修改:
.refreshable { await Task.yield() model.prop = "world" }
方式二:模拟异步操作(贴近真实业务场景)
如果你的实际需求是从网络拉取数据,直接用async/await处理异步任务,自然会延迟属性更新的时机:
.refreshable { // 模拟网络请求延迟,实际替换成你的异步数据获取逻辑 try? await Task.sleep(nanoseconds: 300_000_000) // 0.3秒 model.prop = "world" }
这样修改后,下拉刷新动画结束后才会更新模型,不会和searchable的状态产生冲突,搜索栏就能正常工作了。
内容的提问来源于stack exchange,提问作者IcyHovercraft
相关产品推荐
相关产品推荐

