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

SwiftUI中@Published变量在视图中无法更新的问题求助

问题解决:主视图获取异步加载的用户数量

问题原因

你的问题核心是异步操作的时序问题:getUsers()内部发起的是网络请求,属于异步执行逻辑。当你调用usersList.getUsers()后,代码会立刻执行后续的打印语句,此时网络请求还未完成,users数组仍是初始空状态,所以打印结果为0。而ViewModel里的打印语句是在请求成功的回调中执行的,此时数据已经更新,因此能得到正确的用户数量。

解决方案

方法1:利用SwiftUI自动视图更新(推荐)

SwiftUI会自动监听@Published修饰的变量变化,当users数组更新时,视图会自动刷新。你可以直接在视图中使用usersList.users.count,无需手动处理异步回调:

struct MainView: View {
    @StateObject private var usersList = UserInfoViewModel()
    var body: some View {
        VStack {
            Image("lunchscreen")
            // 数据更新后会自动刷新显示正确数量
            Text("用户数量:\(usersList.users.count)")
        }
        .onAppear(perform: download_Users)
    }
    
    func download_Users() {
        usersList.getUsers()
    }
}

方法2:给ViewModel添加完成回调

如果需要在数据加载完成后执行特定逻辑(比如打印、后续业务处理),可以给getUsers()方法添加回调闭包:

修改ViewModel:
class UserInfoViewModel: ObservableObject {
    @Published var users:[UserDetails] = []
    
    func getUsers(completion: (() -> Void)? = nil){
        let defaults = UserDefaults.standard
        guard let token = defaults.string(forKey: "jsonwebtoken") else {
            completion?()
            return
        }
        APIServices().userInfo(token: token) { (result) in
            switch result {
                case .success(let accounts):
                    DispatchQueue.main.async {
                        self.users = accounts.map(ZoneViewModel.init)
                        print("Number of users in UserInfoViewModel = \(self.users.count)")
                        // 数据更新后触发回调
                        completion?()
                    }
                case .failure(let error):
                    print(error.localizedDescription)
                    completion?()
            }
        }
    }
}
修改主视图的download_Users方法:
func download_Users() {
    usersList.getUsers {
        // 此闭包会在数据更新完成后执行
        print("Number of users in Main view = \(self.usersList.users.count)")
    }
}

方法3:用onReceive监听数据变化

通过SwiftUI的onReceive修饰符,监听users变量的发布事件,当数组更新时执行对应逻辑:

struct MainView: View {
    @StateObject private var usersList = UserInfoViewModel()
    var body: some View {
        Image("lunchscreen")
            .onAppear(perform: download_Users)
            // 监听users数组的变化
            .onReceive(usersList.$users) { updatedUsers in
                print("Number of users in Main view = \(updatedUsers.count)")
            }
    }
    
    func download_Users() {
        usersList.getUsers()
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 14:55:20