I'm having an async call with a completionhandler that fetches data for me through a query. These queries can vary based upon the users action.
My data call looks like this;
class DataManager {
func requestVideoData(query: QueryOn<VideoModel>, completion: @escaping (([VideoModel]?, UInt?, Error?) -> Void)) {
client.fetchMappedEntries(matching: query) { (result: Result<MappedArrayResponse<FRVideoModel>>) in
completion(videos, arrayLenght, nil)
}
}
}
My ViewController looks like this;
DataManager().requestVideoData(query: /*One of the queries below*/) { videos, arrayLength, error in
//Use the data fetched based on the query that has been entered
}
My queries look like this;
let latestVideosQuery = QueryOn<FRVideoModel>().limit(to: 50)
try! latestVideosQuery.order(by: Ordering(sys: .createdAt, inReverse: true))
And this;
let countryQuery = QueryOn<FRVideoModel>()
.where(valueAtKeyPath: "fields.country.sys.contentType.sys.id", .equals("country"))
.where(valueAtKeyPath: "fields.country.fields.countryTitle", .includes(["France"]))
.limit(to: 50)
But I'm not completely sure how I would implement these queries the right way so they correspond with the MVC model.
I was thinking about a switch statement in the DataManager class, and pass a value into the query parameter on my ViewController that would result in the right call on fetchMappedEntries(). The only problem with this is that I still need to execute the correct function according to my query in my VC, so I would need a switch statement over there as well.
Or do I need to include all my queries inside my ViewController? This is something I think is incorrect because it seems something that should be in my model.
In the end I went with a slightly modified networking layer and a router where the queries are stored in a public enum, which I can then use in my functions inside my ViewController. Looks something like this;
public enum Api {
case latestVideos(limit: UInt)
case countryVideos(countries: [String], limit: UInt)
}
extension Api:Query {
var query: QueryOn<VideoModel> {
switch self {
case .latestVideos(let limit):
let latestVideosQuery = QueryOn<VideoModel>().limit(to: limit)
try! latestVideosQuery.order(by: Ordering(sys: .createdAt, inReverse: true))
return latestVideosQuery
case .countryVideos(let countries, let limit):
let countryQuery = QueryOn<VideoModel>()
.where(valueAtKeyPath: "fields.country.sys.contentType.sys.id", .equals("country"))
.where(valueAtKeyPath: "fields.country.fields.countryTitle", .includes(countries))
.limit(to: limit)
return countryQuery
}
}
}
And the NetworkManager struct to fetch the data;
struct NetworkManager {
private let router = Router<Api>()
func fetchLatestVideos(limit: UInt, completion: @escaping(_ videos: [VideoModel]?, _ arrayLength: UInt?,_ error: Error?) -> Void) {
router.requestVideoData(.latestVideos(limit: limit)) { (videos, arrayLength, error) in
if error != nil {
completion(nil, nil, error)
} else {
completion(videos, arrayLength, nil)
}
}
}
}