mardi 28 septembre 2021

SwiftUI MVVM approach with vars in View

I'm building an app in SwiftUI, based on the MVVM design pattern. What I'm doing is this:

struct AddInvestment: View {
    
    @ObservedObject private var model = AddInvestmentVM()
    @State private var action: AssetAction?
    @State private var description: String = ""
    @State private var amount: String = ""
    @State private var costPerShare: String = ""
    @State private var searchText: String = ""
    @State var asset: Asset?
    
    var body: some View {
        NavigationView {
            VStack {
                Form {
                    Section("Asset") {
                        NavigationLink(model.chosenAsset?.completeName ?? "Scegli asset") {
                            AssetsSearchView()
                        }
                    }
                    Section {
                        Picker(action?.name ?? "", selection: $action) {
                            ForEach(model.assetsActions) { action in
                                Text(action.name).tag(action as? AssetAction)
                            }
                        }
                        .pickerStyle(.segmented)
                        .listRowBackground(Color.clear)
                    }
                    Section {
                        TextField("", text: $amount, prompt: Text("Unità"))
                            .keyboardType(UIKit.UIKeyboardType.decimalPad)
                        TextField("", text: $costPerShare, prompt: Text("Prezzo per unità"))
                            .keyboardType(UIKit.UIKeyboardType.decimalPad)
                    }
                }
            }
            .navigationTitle("Aggiungi Investimento")
        }
        .environmentObject(model)
        .onAppear {
            model.fetchBaseData()
        }
    }
}

Then I have my ViewModel, this:

class AddInvestmentVM: ObservableObject {
    
    private let airtableApiKey = "..."
    private let airtableBaseID = "..."
    
    private let assetsTableName = "..."
    private let assetsActionsTableName = "..."
    
    private let airtable = Airtable.init("...")
    
    private var tasks = [AnyCancellable]()
    
    @Published var chosenAsset: Asset?
    @Published var assets = [Asset]()
    @Published var assetsActions = [AssetAction]()
    
    init() { }
    
    func fetchBaseData() {
        
        print("Fetching data...")
        
        let assetActionsRequest = AirtableRequest.init(baseID: airtableBaseID, tableName: assetsActionsTableName, view: nil)
        let assetsActionsPublisher: AnyPublisher<[AssetAction], AirtableError> = airtable.fetchRecords(request: assetActionsRequest)
        
        assetsActionsPublisher
            .eraseToAnyPublisher()
            .sink { completion in
                print("** **")
                print(completion)
            } receiveValue: { assetsActions in
                print("** **")
                print(assetsActions)
                self.assetsActions = assetsActions
            }
            .store(in: &tasks)
    }
}

Now, as you can see I have some properties on the view that are binded to some text fields. Let's take these in consideration:

@State private var description: String = ""
@State private var amount: String = ""
@State private var costPerShare: String = ""
@State private var searchText: String = ""

Keeping in mind the MVVM pattern, should these properties be declared in the ViewModel and binded from there? Or is this a right approach?

Aucun commentaire:

Enregistrer un commentaire