I have inProgress boolean variable in my models, which keeps track of active API requests like this:
class BranchListViewModel: ObservableObject {
@Published var inProgress: Bool = false
func setActive(success: (() -> Void)? = nil, failure: ((RestError?) -> Void)? = nil) {
inProgress = true
putRequest(url: URL(string: K.Api.Url + "/branches/active_status")!, parameters: [:], type:
success?()
self.inProgress = false
} failure: { error in
failure?(error)
self.inProgress = false
}
}
In my view, I'm monitoring this variable with onChange(of:) method. If the variable is false (loading is done) reload data. This approach works fine.
struct BranchListView: View {
@ObservedObject var branchViewModel = BranchListViewModel()
var body: some View {
VStack {
Image("logo")
}
.onChange(of: branchViewModel.inProgress) { value in
if value == false {
branchViewModel.reloadData()
}
}
}
However the problem comes, when I want to update EnvironmentObject variable from onChange(of:) method:
struct BranchListView: View {
@EnvironmentObject var routerViewModel: RouterViewModel
@ObservedObject var branchViewModel = BranchListViewModel()
var body: some View {
VStack {
Image("logo")
}
.onChange(of: branchViewModel.inProgress) { value in
if value == false {
branchViewModel.reloadData()
}
routerViewModel.showLoadingIndicator = value <<<------ problem here
}
}
I want to update routerViewModel variable, which will be then used to show / hide loading indicator. However, when I do so, the .onChange(of:) method is called immediately again with opposite value.
So when I load branchViewModel.setActive() inProgress is set to true and .onChange(of:) is called with value = true (which is correct behaviour). However after assigning routerViewModel.showLoadingIndicater = value, the .onChange(of:) method is called again right away with value = false. Then, when API calls finishes and set inProgress = false, the .onChange(of:) method is not called, because the value was (for unknown reason) already set to false.
I tried put didSet observer to inProgress variable and it has correct behaviour - was set to true when API call started and false when finished.
So the whole process looks like this:
branchViewModel.setActive()
inProgress = true
inProgress didSet -> true
.onChange(of:) -> true
.onChange(of:) -> false <<<--- problem here
API call started
API call processing
API call finished
inProgress = false
inProgress didSet -> false