I have a SwiftUI project using MVVM structure but I have lots of variables in View now, is that right?How can I improve this?
For example, this is my add record view
@State private var money: String = ""
@State private var desc: String = ""
@FocusState var isDescFieldFocused: Bool
@State private var showDatePicker: Bool = false
@State private var showingAlert: Bool = false
@State private var showConstantlyAlert: Bool = false
@State private var showKeyPad: Bool = false
@State private var showCatesPanel: Bool = false
@State private var selectedCate: String = ""
Should I put all these in View Models?
CodePudding user response:
Like you said, you could create a view model for that view, which would either be a @StateObject
or @ObservedObject
(depends on whether you want to create the view model within the view or inject it from outside).
I tend to create view models for my views if they require any logic and not only display information which is passed down from parent views.
Thus, you could do this:
final class YourNameViewModel: ObservableObject {
@Published var money = ""
// other properties
init() {
...
}
}
and use it within your view like so:
struct YourNameView: View {
@StateObject var vm = YourNameViewModel()
// or @ObservedObject var vm: YourNameViewModel (if you want to pass it down from a parent view)
}
CodePudding user response:
Apple addresses this in Data Essentials in SwiftUI WWDC 2020 at 4:18
EditorConfig can maintain invariants on its properties and be tested independently. And because EditorConfig is a value type, any change to a property of EditorConfig, like its progress, is visible as a change to EditorConfig itself. 4:18
So in your case it would look like:
struct MyConfig {
var money: String = ""
var desc: String = ""
var showDatePicker: Bool = false
var showingAlert: Bool = false
var showConstantlyAlert: Bool = false
var showKeyPad: Bool = false
var showCatesPanel: Bool = false
var selectedCate: String = ""
mutating func otherLogic() {}
}
struct MyView {
@State var config = MyConfig()
@FocusState var isDescFieldFocused: Bool
Just to let you know, MVVM (i.e. using objects for view data) is not suitable for SwiftUI because the View struct and property wrappers is equivalent to a view model object but faster and less error-prone. If you use actual objects instead of learning SwiftUI's features you'll have problems.
The time we use an ObservableObject
in SwiftUI is for model data, i.e. the environment object/singleton that stores the arrays of model structs in @Published
properties and is responsible for loading/saving/syncing etc. the model data etc. That is covered in the same video later on, from about 9mins 30secs.
For write-access to model data we use @Binding
.
We used to also use @StateObject
for handling networking or delegates but that is pretty much redundant now we have the task
modifier which does the same thing but better.