Vinod Radhakrishnan
Vinod Radhakrishnan

Reputation: 481

Error in closure tuple parameter

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

Upvotes: 1

Views: 1443

Answers (2)

Sandeep
Sandeep

Reputation: 21144

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.

Upvotes: 3

Sweeper
Sweeper

Reputation: 270980

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) }

Upvotes: 1

Related Questions