如何在SwiftUI中声明viewModel对象?

问题描述

我正在尝试使用@ObservableObject viewmodel,它在我的视图结构中声明为@Observedobject。问题是,当viewmodel更改其“域”属性@Published var时,UI不会更新。另外,我更改了init(){}内的getDomains()函数内的域。看起来好像被叫了两次,为什么会这样呢?这是我的viewmodel代码

Content View

该视图的代码: 进口基金会 导入SwiftUI 导入合并

sizeforItemAt:

有人可以帮我吗?谢谢。

解决方法

引用here的答案

如果可以更改数据,则需要一个动态的ForEach循环(带有显式id参数):

 ForEach(viewModel.domains.indices,id: \.self) { index in // <=
    // ...
 }

在某些情况下,当您尝试修改ForEach循环中使用的数组时,Xcode会警告您:

ForEach(:content :)仅应用于常量数据。而是使数据符合Identifiable或使用ForEach(:id:content :)并提供明确的ID!

经过测试的代码


struct DomainsOfInterestView: View {

    @ObservedObject var viewModel: DomainsViewModel = DomainsViewModel()
    
    @State var isActive = true
    
    var body: some View {
            VStack(alignment: .center) {
                HStack {
                    Text("Choose domains of interest for your profile")
                        .font(.headline)
                    Spacer()
                }.padding(.bottom,16)
                
                ForEach(viewModel.domains.indices,id: \.self) { index in // <=
                    Text(String(index))
                }

                Button(action: {
                }) {
                    Text("Save")
                }.padding(.top,30)
                    .padding([.leading,.trailing],30)
                Spacer()
            }.padding([.leading,12)
            .navigationBarTitle("Domains of interest")
    }
}


class DomainsViewModel: ObservableObject {

    @Published var domains: [Int] = [Int]()
    
    init() {
        self.getDomains { (response) in
            print(response)
        }
    }
    
    func getDomains(completion: @escaping (Bool) -> Void) {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.domains = [1,2,3,4,5]
            completion(true)
        }
    }

}

在iOS 14 beta 6上使用Xcode 12 beta 6进行了测试

, 在每次更新视图模型时都会重新创建

DomainsOfInterestView。然后,您每次都使用新的DomainsViewModel实例初始化视图模型属性。新的视图模型会将domains属性设置为[InterestDomain](),并且将再次调用self.getDomains

首先,最好将ViewModel插入启动器中的DomainsOfInterestView中,如@youjin在上一篇文章的评论中所写。此外,如果最低部署目标允许,则可以使用@StateObject代替@ObservedObject。在这种情况下,不会在每次更新视图时重置viewModel属性。