【问题标题】:SwiftUI ObservableObject not updating when value is Published发布值时,SwiftUI ObservableObject 未更新
【发布时间】:2020-12-05 05:15:41
【问题描述】:

我有一个视图和一个 viewModel,当用户添加到用户数组时,它应该更新 ListView。我可以验证是否正在添加用户,但 ObservedObject 没有更新。

我有一个搜索栏,可让您搜索用户,然后更新 ViewModel 中的用户数组,该数组应该更新 View,但它没有。

视图模型

class UsersViewModel: ObservableObject {
    @Published var users: [User] = []
    @Published var isLoading = false
    var searchText: String = ""
    
    func searchTextDidChange() {
        isLoading = true
        API.User.searchUser(text: searchText) { (users) in
            self.isLoading = false
            self.users = users
        }
        // confirmed that users has data now at this point
    }
}

查看

struct UsersView: View {
    @ObservedObject var usersViewModel = UsersViewModel()
    
    var body: some View {
        VStack() {
            SearchBarView(text: $usersViewModel.searchText, onSearchButtonChanged: usersViewModel.searchTextDidChange)
            
            // Not getting called after usersViewModel.users gets data
            if (usersViewModel.users.count > 0) {
                Text(usersViewModel.users[0].username)
            }
        }
    }
}

【问题讨论】:

    标签: swiftui observable observableobject observedobject


    【解决方案1】:

    您可能会使用不同的 UsersViewModel 对象:

    @ObservedObject var usersViewModel = UsersViewModel()
    

    由于 UsersView 是一个结构,因此每次实例化 View 时都会创建一个新模型(这种情况经常发生,而不仅仅是在视图出现时)。在 iOS 14 中,@StateObject 将 State(保留 View 实例化之间的信息)与 ObservedObject 结合起来,但在 iOS 13 中,如果 ObservedObject 不是共享实例,我建议传入它。

    【讨论】:

    • 我不认为是这样。异步数据似乎有问题。如果我在视图中创建一个按钮,然后让它在 ViewModel 中切换一个值,那效果很好。但是如果我通过我的异步 API 调用运行它,它就不起作用(即使异步调用返回数据并更新 Published 变量)
    • 如果我的理论是正确的,您可以通过在UsersViewModel.init 中放置断点来检查。如果它触发不止一次,那么你就会遇到这个问题(即使它不是这个特定错误的原因)。
    • 你确实是对的。它正在初始化一堆。所以你是说我应该在实例化 View 之前创建 ViewModel,然后将 ViewModel 传入?
    • 是的,这就是你想要做的(至少在 iOS 13 中)
    • 我正在通过 NavigationBarButton 中的 NavigationLink 进入视图。每当我点击它时, NavigationBarButton 会被调用 3 次,因此即使我将 UserViewModel() 传递给 View,它仍然会被多次初始化,因为 View 会被多次初始化,因为 NavigationLin 会被多次初始化,因为 NavigationBarButton 会被初始化多次初始化
    【解决方案2】:

    尝试更新主队列

    API.User.searchUser(text: searchText) { (users) in
       DispatchQueue.main.async {
          self.isLoading = false
          self.users = users
       }
    }
    

    【讨论】:

    • 不。什么都没有
    猜你喜欢
    • 2021-02-27
    • 2021-10-14
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-04
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多