如何在 SwiftUI 中声明 viewModel 对象? [英] How should the viewModel object be declared in SwiftUI?

查看:75
本文介绍了如何在 SwiftUI 中声明 viewModel 对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用在我的视图结构中声明为 @ObservedObject 的 @ObservableObject viewModel.问题是当 viewModel 改变它的域"时.属性@Published var,UI 未更新.另外,我更改了在 init() {} 中调用的 getDomains() 函数内的域.看起来它被调用了两次,为什么会发生这种情况?这是我的 viewModel 代码:

I am trying to use an @ObservableObject viewModel which is declared as @ObservedObject inside my view struct. The problem is that when the viewModel changes it's "domains" property @Published var, the UI is not updating. Also, I change domains inside getDomains() function which is called inside init() {}. Looks like it is called twice, why is that happening? Here's my code for viewModel:

import Combine

class DomainsViewModel: ObservableObject {

    @Published var domains: [InterestDomain] = [InterestDomain]()
    
    init() {
        self.getDomains { (response) in
            print(response)
        }
    }
    
    func getDomains(completion: @escaping (Bool) -> Void) {
        NetworkEngine.shared.appNetwork.getInterestDomains { result in
            self.domains.removeAll()
            switch result {
            case .success(let domainsOfInterest):
                if let domainsList = domainsOfInterest {
                    self.domains = domainsList
                }
                completion(true)
            case .failure(_):
                completion(false)
            }
        }
    }

}

视图代码:进口基金会导入 SwiftUI导入组合

Code for the view: import Foundation import SwiftUI import Combine

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) { index in
                    DomainOfInterestElement(isActive: self.$isActive, domain: self.viewModel.domains[index].name)
                }

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

struct DomainsOfInterestView_Previews: PreviewProvider {
    static var previews: some View {
    DomainsOfInterestView()
    }
}

struct DomainOfInterestElement: View {
    @Binding var isActive: Bool
    var domain: String
    var body: some View {
        Button(action: {
            self.isActive.toggle()
        }) {
            VStack {
                Divider().padding(.bottom, 12)
                HStack {
                    checkBoxView()
                        .frame(width: 36, height: 36)
                    textView().font(.custom("SFProDisplay-Regular", size: 16))
                    Spacer()
                }
            }
        }
    }
    
    func checkBoxView() -> Image {
        switch isActive {
        case true:
            return Image(uiImage: #imageLiteral(resourceName: "check-box-active-2-1")).renderingMode(.original)
        case false:
            return Image(uiImage: #imageLiteral(resourceName: "check-box-active-1")).renderingMode(.original)
        }
    }
    func textView() -> Text {
        switch isActive {
        case true:
            return Text(domain)
                .foregroundColor(.black)
        case false:
            return Text(domain)
                .foregroundColor(Color.orGrayColor)
        }
    }
}

有人可以帮我吗?谢谢.

Could anyone help me please? Thanks.

推荐答案

DomainsOfInterestView 在其视图模型的每次更新时重新创建.并且每次都使用新的 DomainsViewModel 实例初始化视图模型属性.一个新的视图模型会将 domains 属性设置为 [InterestDomain]() 并且 self.getDomains 将被再次调用.

DomainsOfInterestView is recreated on every update of its view model. And you initialise the view model property with a new DomainsViewModel instance every time. A new view model will have the domains property set to [InterestDomain]() and self.getDomains will be called again.

首先,最好将 viewModel 注入到初始化器中的 DomainsOfInterestView,正如@youjin 在上一篇文章的评论中所写的那样.此外,如果您的最低部署目标允许,您可以使用 @StateObject 而不是 @ObservedObject.在这种情况下,每次更新视图时都不会重置 viewModel 属性.

First of all, better to inject the viewModel to DomainsOfInterestView in an initiailiser as @youjin wrote in a comment to the previous post. Also, you can use @StateObject instead of @ObservedObject if your minimum deployment target allows that. In this case, the viewModel property won't be reset every time the view is updated.

这篇关于如何在 SwiftUI 中声明 viewModel 对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆