0

I have a base class where I'm making an api call and changing the state of the api like so

class ProfileBaseViewModel {
    @Published private(set) var apiState: APIState = .initial
    private(set) var settingsData: SettingModel?    
    var cancellables: Set<AnyCancellable> = Set<AnyCancellable>()

    func getSettingsData() {
        apiState = .inProgress
        interactor.getSettingsData()
            .sink(receiveCompletion: { [weak self] error in
                if case .failure(_) = error {
                    self?.apiState = .completed(didSucceed: false)
                }
            }, receiveValue: { [weak self] response in
                guard let self: ProfileBaseViewModel = self else { return }
                self.settingsData = response
                self.apiState = .completed(didSucceed: true)
            })
            .store(in: &self.cancellables)
    }
}

This base class has two child view model's like so. Notice how getSettingsData is only being called in ProfileViewModel, this is because SettingsVC is pushed on top of ProfileVC and expectation is that ProfileVC/VM will make the api call and only the api state will be observed in SettingsVC/VM

final class ProfileViewModel: ProfileBaseViewModel {
    init() {
        getSettingsData()
    }
}

final class SettingViewModel: ProfileBaseViewModel {
}

These two view models are attached to two view controllers like so

extension ProfileViewController {
    func observeViewModel() {
        self.viewModel.$apiState
            .receive(on: DispatchQueue.main)
            .sink { [weak self] state in
                self?.handleAPIState(state: state)
            }
            .store(in: &super.cancellables)
    }
    
    private func handleAPIState(state: APIState) {
        switch state {
        case .initial:
            break
        case .inProgress:
            ///show loader
        case .completed(let didSucceed):
            ///reload table
        }
    }
}

extension SettingsViewController {
    func observeViewModel() {
        self.viewModel.$apiState
            .receive(on: DispatchQueue.main)
            .sink { [weak self] state in
                self?.handleAPIState(state: state)
            }
            .store(in: &super.cancellables)
    }
    
    private func handleAPIState(state: APIState) {
        switch state {
        case .initial:
            break
        case .inProgress:
            ///show loader
        case .completed(let didSucceed):
            ///reload table
        }
    }
}

This doesn't work as expected, handleAPIState in SettingsVC is only called for initial state and not for inProgress or completed, it works as expected for ProfileVC. Any help is appreciated.

Ameya Vichare
  • 1,119
  • 1
  • 10
  • 22

0 Answers0