1

I'm trying to write an API layer using RxSwift and RxAlamofire. Here is the code for API request.

public func _request(_ method: Alamofire.HTTPMethod, url: URLConvertible, parameters: [String : Any]? , encoding: ParameterEncoding, headers: [String : String]?, isSecondTryAfterAuth: Bool = false) -> RxSwift.Observable<(HTTPURLResponse, Any)>
{
    return RxAlamofire
        .requestJSON(method, url, parameters: parameters, encoding: JSONEncoding.default, headers: self.appDelegateInstance.refreshToken)
        .map({ (response, json) -> Observable<(HTTPURLResponse, Any)> in
            return Observable.just(response, json)
        })
}

I got an error in .map function "Closure tuple parameter '(HTTPURLResponse, Any)' does not support destructuring". Any idea about how to solve this?enter image description here

Vinod Radhakrishnan
  • 441
  • 1
  • 6
  • 18

2 Answers2

3

You are using map method, which has the following method signature.

/**
     Projects each element of an observable sequence into a new form.

     - seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)

     - parameter transform: A transform function to apply to each source element.
     - returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.

     */
public func map<R>(_ transform: @escaping (Self.E) throws -> R) -> RxSwift.Observable<R>

As you can see, the transform closure is only supposed to change the elements to the type you want your Observable to be. In your case however, it seems like you are trying to return an Obsevable of <(HTTPURLResponse, Any)> ie. Observable<(HTTPURLResponse, Any)> as it can be seen from _request method signature but instead you return Observable<Observable<(HTTPURLResponse, Any)>> and that is why you get the error.

Look at this simple example,

let b = Observable.of(1, 2, 3, 4, 5).map { "\($0 + 1)" }

The example transforms element and adds 1 to each element and returns it as string.. Here, you are transforming each element.

The type of b at this point is Observable<String>

In your above example, you change it in such a way that you are returning observable from map again.

Your code can be visualized like this,

let b = Observable.of(1, 2, 3, 4, 5).map { Observable.just("\($0 + 1)) }

Now, b is not Observable<String> instead it is Observable<Observable<String>>.

This is exactly the problem that you have with your code.

This is your _request method,

public func _request(_ method: Alamofire.HTTPMethod, url: URLConvertible, parameters: [String : Any]? , encoding: ParameterEncoding, headers: [String : String]?, isSecondTryAfterAuth: Bool = false) -> RxSwift.Observable<(HTTPURLResponse, Any)>

The expected return type is rather Observable<(HTTPURLResponse, Any)>

But you do some magic and return,

Observable<Observable<(HTTPURLResponse, Any)>>

Based on the return type of your method, I am hoping this is what you were trying to do,

return RxAlamofire
    .requestJSON(method, url,
                 parameters: parameters,
                 encoding: JSONEncoding.default,
                 headers: self.appDelegateInstance.refreshToken)
    .map( { (response, json) -> (HTTPURLResponse, Any) in
        return (response, json)
    })

By the way, the map at the end looks redundant, since it is simply returning the input, unless you plan to transform the input type (response, json) to some other type.

Sandeep
  • 20,908
  • 7
  • 66
  • 106
1

The closure apparently has only one parameter that is a tuple of two values (HTTPURLResponse and Any), yet the way you wrote (response, json) tells swift that you are trying to deconstruct the single tuple parameter into 2 parameters, which is not allowed.

You have to write it as one parameter:

.map({ tuple -> Observable<(HTTPURLResponse, Any)> in
    return Observable.just(tuple)
})

You can also write it like this if the types can be inferred:

.map { Observable.just($0) }
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • I got an error in return Observable.just(tuple.0, tuple.1) "Missing argument label 'scheduler:' in call" – Vinod Radhakrishnan Apr 18 '18 at 09:45
  • @VinodRadhakrishnan Actually, what are you trying to do with the `Observable`? Do you just want to create an `Observable` with just one value? It makes no sense to pass 2 arbitrary arguments into `Observable.just`. See the edited answer. Maybe that's what you meant? – Sweeper Apr 18 '18 at 10:02
  • my requirement is to return httpResponse and json data. I'm a beginner in RxSwift, so don't know I'm doing it in a right way. – Vinod Radhakrishnan Apr 18 '18 at 10:08
  • @VinodRadhakrishnan Judging from the return type of the surrounding function, it seems like my answer would work. I suggest you learn more about RxSwift first. – Sweeper Apr 18 '18 at 10:10