swiftmvvmserveralamofirecompletionhandler

Passing server response to ViewModel MVVM


I have been trying to pass the response of my AF.request statement to my viewModel but am unable to understand still? I need to pass my response to my ViewModel and then use it to display in the tableView.

This is my Service Class:

Service

class Service {
    
  fileprivate var baseUrl = ""
    //https://api.themoviedb.org/3/tv/76479?api_key=3d0cda4466f269e793e9283f6ce0b75e&language=en-US
    init(baseUrl: String) {
        self.baseUrl = baseUrl
    }
    var tvShowDetails = TVShowModel()
    
    func getTVShowDeet(completionHandler: @escaping ()-> TVShowModel){
        let request = AF.request(self.baseUrl)
        .validate()
        .responseDecodable(of: TVShowModel.self) { (response) in
            guard let tvShow = response.value else {return}
            return tvShow
            print("printing response", tvShow)
        }
     }
}

ViewModel

 func getTVShowDetails(){
    service.getTVShowDeet{
        print(self.response)
        self.delegate?.reloadTable()
        self.headerDelegate?.configureHeader()
        print("prinitn respinse in VM", self.response)
    }
 }

Model

struct TVShowModel : Decodable {    
    let id : Int?
    let original_name : String?
    let overview : String?

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case original_name = "original_name"
        case overview = "overview"
    }

    init(){
        id = nil
        original_name = nil
        overview = nil    
    }
}

Solution

  • Networking requests are asynchronous meaning we don't know when they'll complete so we need to use completion handlers instead of returning from the function (unless you use Async/Await). Something along the lines of this should work:


    Service

    func getTVShowDeet(completionHandler: @escaping (TVShowModel) -> Void) {
        let request = AF.request(self.baseUrl)
        .validate()
        .responseDecodable(of: TVShowModel.self) { (response) in
            guard let tvShow = response.value else { return }
            completionHandler(tvShow)
        }
     }
    

    ViewModel

     func getTVShowDetails() {
        service.getTVShowDeet { [weak self] tvShow in
            
            // Here you may need to store the tvShow object somewhere to use in your tableView datasource.
    
            self?.delegate?.reloadTable()
            self?.headerDelegate?.configureHeader()
        }
     }