As part of a network layer for a specific API call, we have a function which builds a required URL. As part of this we have an array of query items e.g.:
component?.queryItems = [
URLQueryItem(name: "name", value: name),
URLQueryItem(name: "age", value: age),
URLQueryItem(name: "gender", value: gender),
URLQueryItem(name: "nextOfKin", value: nextOfKin)
]
These items are always present and non optional. We then have a bunch of optional items which we unwrap and spend to the query array if they are present and not empty. For example:
if let urlQuery, !urlQuery.isEmpty {
component?.appendQueryItem(param: "url", value: urlQuery)
}
if let searchText, !searchText.isEmpty {
component?.appendQueryItem(param: "text", value: searchText)
}
if let filterTerm, !filterTerm.isEmpty {
component?.appendQueryItem(param: "filter", value: filterTerm)
}
Here is the appendQueryItem
method which is part of an extension to URLComponents
:
mutating public func appendQueryItem(param: String, value: String) {
var queryItems: [URLQueryItem] = self.queryItems ?? [URLQueryItem]()
queryItems.append(URLQueryItem(name: param, value: value))
self.queryItems = queryItems
}
However, we have a predefined order in which we want params to be added to the url:
urlQuery searchText name age filterTerm gender nextOfKin
With this in mind, I'm wondering what would be the cleanest way to approach this to ensure the correct order is followed.
I had considered something like:
component?.queryItems = [
URLQueryItem(name: "urlQuery", value: urlQuery?.isEmpty == false ? urlQuery : nil),
URLQueryItem(name: "searchText", value: searchText?.isEmpty == false ? searchText : nil),
URLQueryItem(name: "name", value: name),
URLQueryItem(name: "age", value: age),
URLQueryItem(name: "filterTerm", value: filterterm?.isEmpty == false ? filterTerm : nil),
URLQueryItem(name: "gender", value: gender),
URLQueryItem(name: "nextOfKin", value: nextOfKin)
].compactMap { $0 }
This works, but it is quite messy and we also try to avoid conditionally unwrapping bools like this i.e. we would preferably have:
if let searchText, !searchText.isEmpty {}
I'd also like to avoid inserting these at a specified index as this will easily break in the future if any further params are added.