Search code examples
iphoneswiftrx-swiftmoya

Mapping moya result with moya_modelMapper


I have the following function in my webservice class:

 func loadTransport() -> Observable<[TransportResponse]> {
        let nonce = "\(Date().timeIntervalSince1970)"
        let csaKey = try! config.apikey()
        let csaSecret = try! config.apiSecret()

        let csaSignature = crypto.generateSignature(nonce: nonce, url: "http://*****/v1/nmbs", body: "", secret: csaSecret)
        print("SIGNATURE = \(csaSignature)")

        let endpointClosure = { (target: TransportService) -> Endpoint<TransportService> in
            let url = target.baseURL.appendingPathComponent(target.path).absoluteString
            let endpoint = Endpoint<TransportService>(URL: url, sampleResponseClosure: {.networkResponse(200, target.sampleData)}, method: target.method, parameters: target.parameters)
            return endpoint.adding(newHttpHeaderFields: ["CSA-KEY": csaKey,"CSA-NONCE": nonce,"CSA-SIGNATURE": csaSignature])
        }



        let provider = RxMoyaProvider<TransportService>(endpointClosure: endpointClosure, plugins: [NetworkLoggerPlugin(verbose: true)])
        return provider
            .request(TransportService.nmbs)
            .filterSuccessfulStatusCodes()
            .mapArray(type: TransportResponse.self)
    }

And in my TransportViewModel I have this init method:

 init(webService: Webservice) {
        self.webService = webService

        title.value = String.localizedString(key: "transport_title")



        transportResponse = active.asObservable()
            .filter { $0 }
            .flatMap {  _  in
                return webService.loadTransport()
            }
            .map { response in
                return [TransportData(items: response)]
        }    
    }

The problem is it comes in my flatMap method but it never comes inside the map below the flatMap.

When I add a subscribe part to my webservice function like this:

 let provider = RxMoyaProvider<TransportService>(endpointClosure: endpointClosure, plugins: [NetworkLoggerPlugin(verbose: true)])
    provider
        .request(TransportService.nmbs)
        .filterSuccessfulStatusCodes()
        .mapArray(type: TransportResponse.self)
        .subscribe { event in
            switch event {
            case .next(let response):
                print(response)
            case .error(let error):
                print(error)
            default: break
            }
    }.addDisposableTo(disposeBag)

I see that my response is correctly printed. Can anybody help me with this?


Solution

  • The issue is that your provider gets deallocated as soon as loadTransport() method is finished.

    You are using the old version of Moya. Until this pull request RxMoyaProvider was captured weakly, so the whole chain would not emit any event at all (next/error/completed).

    To fix that, covert provider to a class-scoped variable:

    class Webservice {
        var provider: RxMoyaProvider<TransportService>?
    }
    

    And use it like this:

    self.provider = RxMoyaProvider<TransportService>(endpointClosure: endpointClosure, plugins: [NetworkLoggerPlugin(verbose: true)])
    return self.provider!
        .request(TransportService.nmbs)
        .filterSuccessfulStatusCodes()
        .mapArray(type: TransportResponse.self)