You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用异步数据更新SwiftUI视图?

问题原因及解决方案

你的代码里视图不更新的核心原因有两个:

  • CurrentUser 类没有实现 ObservableObject,也未用 @Published 标记需要监听的属性,SwiftUI无法感知它的属性变化
  • ContentView 里的 currentUser 是普通常量(let),即便内部属性变化,视图也不会重新渲染

修正步骤:

  1. 让CurrentUser成为可观察对象
    给CurrentUser添加ObservableObject协议,并将需要监听的属性标记为@Published,让SwiftUI能捕捉到属性变化。

  2. 在视图中正确监听用户对象
    把ContentView里的currentUser从普通常量改成@ObservedObject,或者直接监听UserService的单例对象(因为它是全局共享的)。

修改后的完整代码:

import SwiftUI
import Foundation

class CurrentUser: ObservableObject {
    @Published var id = ""
    @Published var nickname = ""
}

class UserService {
    @Published var currentUser = CurrentUser()
    static var shared = UserService()
    private init() {
    }
}

class ViewModel: ObservableObject {
    func fetchCurrentUser() async {
        let currentUser = UserService.shared.currentUser
    
        // CurrentUser的属性是@Published,修改会自动触发视图更新
        currentUser.id = "007"
        currentUser.nickname = "James Bond"
    }
}

struct ContentView: View {
    @StateObject private var viewModel = ViewModel()
    @ObservedObject private var userService = UserService.shared

    var body: some View {
        VStack(spacing: 10) {
            Text("ID: \(userService.currentUser.id)")
            Text("Nickname: \(userService.currentUser.nickname)")
        }
        .task {
            await viewModel.fetchCurrentUser()
        }
    }
}

额外说明:

  • 如果不想让UserService直接持有@Published的currentUser,也可以让ViewModel持有一个@Published的CurrentUser实例,然后在视图中绑定viewModel.currentUser。
  • 异步函数fetchCurrentUser里的修改不需要额外的DispatchQueue或MainActor,因为@Published属性的修改会自动在主线程触发视图更新(如果是在后台线程修改,才需要切换到主线程,你的代码是同步修改,无需额外操作)。

内容的提问来源于stack exchange,提问作者CeilingTiles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:39:53