WishIHadThreeGuns
WishIHadThreeGuns

Reputation: 1469

Swift closure conform to typealias including Any

I have two typealias declarations

typealias QueryClosure = ((UInt?,UInt?)->([URLQueryItem])?)?
typealias SearchClosure = ((String?,UInt?)->([URLQueryItem])?)?

And I created closures for these

var queryFunc: (QueryClosure)? = ( {a,b in
    return [URLQueryItem(name: "limit", value: "\(a ?? defaultPageSize)"), URLQueryItem(name: "offset", value: "\( (b ?? defaultPageIndex) * (a ?? defaultPageSize) )")]
})

var searchFunc: (SearchClosure)? = ( {query,b in
    return [URLQueryItem(name: "q", value: query), URLQueryItem(name: "page", value: "\(b ?? defaultPageIndex)")]
    }
)

Now I don't want to pass either a query or a search closure, I want to pass a general closure.

So I created a new typealias

typealias VariableClosure = ((Any?, Any?)->([URLQueryItem]))?

But I'm not able to convert to this type

let search : (VariableClosure) = ( {query,b in
    return [URLQueryItem(name: "q", value: query), URLQueryItem(name: "page", value: "\(b ?? defaultPageIndex)")]
    }
)

This gives me the error that

Cannot convert value of type '(String?, _) -> [URLQueryItem]' to specified type 'VariableClosure' (aka 'Optional<(Optional<Any>, Optional<Any>) -> Array<URLQueryItem>>')

How can I create a closure (or better two) that conform to the typealias variableclosure, or in some other way have a kind of generic typealias that I can pass my closures to.

Upvotes: 0

Views: 64

Answers (1)

PGDev
PGDev

Reputation: 24341

Since URLQueryItem accepts a String and the query variable the you are passing is of Any type, you must first typecast query to String before using it.

Same goes for variable b. You must typecast it to Int before using.

let search: VariableClosure = {query,b in
    if let query = query as? Int, let b = b as? Int {
        return [URLQueryItem(name: "limit", value: "\(query ?? 10)"), URLQueryItem(name: "offset", value: "\( (b ?? 10) * (query ?? 10) )")]
    } else if let query = query as? String, let b = b as? Int {
        return [URLQueryItem(name: "q", value: query), URLQueryItem(name: "page", value: "\(b ?? 1)")]
    }
    return nil
}

In the above case, if you are expecting query and b of other types as well, you must handle them manually.

Upvotes: 1

Related Questions