SwiftUI + Combine framework + MVVM Publisher return empty list

516 Views Asked by At

I am using the MVVM architecture in Swift-UI with Combine Framework and Alamofire. However the data is being returned to observable object and is printing means the Alamofire and published data from api layers but from obserable object its not going to view. I print the response and its printing in publisher but not returning back to view.

Following is the observable object.

import SwiftUI
import Combine

class CountryViewModel: ObservableObject {
    
    @Published var countryResponse:[CountryResponse] = []
    
    @Published var isLoggedIn = false
    @Published var isLoading = false
    
    @Published var shouldNavigate = false
    
    private var disposables: Set<AnyCancellable> = []
    
    var loginHandler = CountryHandler()
    
    @Published var woofUrl = ""
    
    private var isLoadingPublisher: AnyPublisher<Bool, Never> {
        loginHandler.$isLoading
            .receive(on: RunLoop.main)
            .map { $0 }
            .eraseToAnyPublisher()
    }
    
    private var isAuthenticatedPublisher: AnyPublisher<[CountryResponse], Never> {
        loginHandler.$countryResponse
            .receive(on: RunLoop.main)
            .map { response in
                guard let response = response else {
                    return []
                }
                print(response)
                return response
            }
        .eraseToAnyPublisher()
    }
    
    init() {
        countryResponse = []
        isLoadingPublisher
            .receive(on: RunLoop.main)
            .assign(to: \.isLoading, on: self)
            .store(in: &disposables)
        
        isAuthenticatedPublisher.map([CountryResponse].init)
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: { [weak self] value in
              guard let self = self else { return }
              switch value {
              case .failure:
                self.countryResponse = []
              case .finished:
                break
              }
              }, receiveValue: { [weak self] weather in
                guard let self = self else { return }
                self.countryResponse = weather
            })
            .store(in: &disposables)
           //        isAuthenticatedPublisher
          //            .receive(on: RunLoop.main)
         //            .assign(to: \.countryResponse, on: self)
        //            .store(in: &disposables)
    }
        
    public func getAllCountries(){
        loginHandler.getCountryList()
    }
    
    public func getAllUnis(_ id:Int){
        loginHandler.getCountryList()
    }
}

View Code

struct ContentViewCollection: View {
    
    @Binding var selectedCountryId:Int
    var axis : Axis.Set = .horizontal
    var viewModel:CountryViewModel
    @State var countries:[CountryResponse] = []
    
    var body: some View {
        ScrollView (.horizontal, showsIndicators: false) {
            HStack {
                ForEach(self.viewModel.countryResponse) { (postData) in
                    Button(action: {
                        self.selectedCountryId = postData.countryID ?? 0
                    }){
                        WebImage(url: self.imageURL(postData.countryName ?? ""))
                            .resizable()
                            .indicator(.activity)
                            .scaledToFit()
                            .frame(minWidth: 40,maxWidth: 40, minHeight: 40, maxHeight: 40, alignment: .center)
                    }
                    
                }
            }
        }.onAppear() {
            self.loadData()
        }
    }
}

Thanks in advance.

0

There are 0 best solutions below