I have a view model class with multiple @Published
properties.
class AddPassaround : ObservableObject {
@Published var name: String = ""
@Published var reversed : String = ""
@Published var password: String = ""
@Published var age: String = ""
@Published var address: String = ""
@Published var oneAnotherProperty: String = ""
init() {
}
}
Whenever any one of the @Published
property is updated, I call an API. Now there is another scenario that needs to update multiple @Published
properties at once programmatically. Something like this
viewModel.name = "test"
viewModel.password = "newPassword"
viewModel.oneAnotherProperty = "notUpdateAll"
Now the problem is the API is called multiple times and view is reloaded multiple times. How can I make the API to call only once in this case only. It should work normally in other cases.
CodePudding user response:
Create a Bool
property to keep track of whether the API has already been called. You can set this property to true when the API is called, and check its value before calling the API again. If the property is true, you can simply return from the function without calling the API again.
Here is an example of how you could implement this:
class AddPassaround : ObservableObject {
@Published var name: String = ""
@Published var reversed : String = ""
@Published var password: String = ""
@Published var age: String = ""
@Published var address: String = ""
@Published var oneAnotherProperty: String = ""
// Add a new property to keep track of whether the API has been called
var calledAPI: Bool = false
init() {
}
// Update the function that calls the API to check the value of calledAPI
// before calling the API
func updateAPI() {
if calledAPI {
return
}
// Call the API here
// Set calledAPI to true to indicate that the API has been called
calledAPI = true
}
}
CodePudding user response:
The easy answer is to remove @Published
and call objectWillChange.send()
when you want to the View
to update.
The long answer is to substitute @Published
with your own implementation.
class AddPassaroundVM : ObservableObject {
var name: String = ""{
//Substitute for @Published
didSet{
if autoUpdate{
updateNow()
}
}
}
//Keeps track of when to update
private (set) var autoUpdate: Bool = true
///Toggles the ability to update with every change
func toggleAutoUpdate(){
autoUpdate = !autoUpdate
updateNow()
}
///Signals to update
func updateNow(){
objectWillChange.send()
}
}
struct AddPassaroundView: View {
@StateObject var vm: AddPassaroundVM = .init()
var body: some View {
VStack{
TextField("name", text: $vm.name)
Text(Array(arrayLiteral: vm.name).reversed().joined())
Button("auto update \(vm.autoUpdate ? "on" : "off")", action: vm.toggleAutoUpdate)
Button("update now", action: vm.updateNow)
}.textFieldStyle(.roundedBorder)
}
}