SwiftUI如何从ViewModel修改视图@State属性及绑定DatePicker
你遇到的警告是因为@State是仅用于视图层的属性包装器,不能放到ObservableObject类型的ViewModel中使用,对应的警告翻译为:在未安装到视图上时访问State的值,这将导致绑定始终为初始常量值,不会更新。
正确实现步骤
第一步:调整ViewModel代码
在ViewModel中用@Published修饰时间属性,接口请求成功后直接修改该属性即可:
import SwiftUI class BookTimeViewModel: ObservableObject { // 用@Published修饰需要同步到视图的属性 @Published var startTime = Date.now // 你原有的后端接口请求方法 func loadStartTimeFromServer() { // 此处替换为你的实际网络请求逻辑 URLSession.shared.dataTask(with: URL(string: "你的接口地址")!) { [weak self] data, response, error in // 接口请求成功,解析得到后端返回的时间 if let data = data, let serverTime = try? JSONDecoder().decode(Date.self, from: data) { // 必须切回主线程修改UI相关属性 DispatchQueue.main.async { self?.startTime = serverTime } } }.resume() } }
第二步:调整视图层代码,直接和ViewModel绑定
不需要在视图中单独定义@State的startTime,直接把DatePicker的绑定指向ViewModel的属性即可:
struct BookTimeView: View { // 如果当前视图持有ViewModel,iOS14及以上推荐用@StateObject @StateObject var viewModel = BookTimeViewModel() // 如果ViewModel是从外部传入的,保留你原来的@ObservedObject即可 var body: some View { DatePicker("选择时间", selection: $viewModel.startTime, displayedComponents: .hourAndMinute) .onAppear { // 页面加载时调用接口拉取初始时间 viewModel.loadStartTimeFromServer() } } }
问题解答
- 如何从ViewModel中修改startTime的值?
只需将startTime声明为ViewModel中@Published修饰的属性,接口请求成功后在主线程直接给该属性赋值即可,属性变更会自动通知视图刷新。 - 是否可以直接将DatePicker和ViewModel绑定?
完全可以,就是上面实现的方式,只要属性用@Published修饰,直接用$viewModel.startTime的格式生成绑定传给DatePicker即可。
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

