My app must fetch JSON via HTTPS request, and then parse that data.
What I'm looking for is to have a "one function rules all" approach to it, like so.
func call(endpoint: String) {
let url = URL(string: "https://example.com/api/" endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// Parse JSON here without using a model.
// Just convert the data into a JSON object and return it
}
}
Every single example code I've come across seems to me that you need to make a model with the expected values, and then do this:
JSONDecoder().decode(ModelHere.self, from: data)
This means that I need to make a new function for each endpoint.
Why not just use a separate function for each endpoint?
I have a lot of endpoints that could be called from within a function.
Creating a new function for each endpoint to pass it a separate model to then parse the data from the response ... that is a lot of junk to sift through in the code.
I'm sure there is a better way to do it that is just obscure, or I'm missing.
Essentially, I'm looking for this:
a function needs remote data to load a view -> fires call('endpoint/example/') -> call() returns the json object -> the function can now take the data it needs
Multiple processor functions, one call() function. I hope I'm making sense.
Thanks
EDIT
Here is the solution to the problem:
private var host = "https://jsonplaceholder.typicode.com/"
func call<T: Codable>(endpoint: String, completion: @escaping (T)->()) {
let url = URL(string: host endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
do {
let model = try JSONDecoder().decode(T.self, from: data!)
completion(model)
} catch let error {
print(error.localizedDescription)
}
}.resume()
}
Please make your necessary adjustments as this has just been lifted from my playground env, can't guarantee it's "proper".
CodePudding user response:
That's what generic is for, for instance:
You can define T as a your date model which is a generic type, and you fetch it and return it with completion. Making T as codable so any model that conforms codable will make this call.
func call<T: Codable>(endpoint: String, completion: (T) -> ()) {
let url = URL(string: "https://example.com/api/" endpoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
// Parse JSON here without using a model.
// Just convert the data into a JSON object and return it
let model = JSONDecoder().decode(T.self, from: data)
completion(model)
}
}
And when you call the function:
call(endpoint: "something") { model: ModelHere in
// Use your model
}
So you don't have to make separate functions for every model you have.
** Code not been tested, just as an idea
