Reputation: 3301
I want to Pass a generic model object in swift.
Currently I have a closure that have to return the Model object as below
completionHandler = ([ModelObject]?, Error?) -> Void
Method calling
func method1( onCompletion: @escaping completionHandler) -> Void {
}
I want to make a generic completionhandler that can pass different model instead of specific Model. Note:- all model object conform to Codable protocol as below
struct ModelObject: Codable {
}
//===== Edit======
func method1<M: Codable>( onCompletion: @escaping (M?, Error?) -> Void) -> Void {
let decoder = JSONDecoder()
let items = try? decoder.decode(ModelObject.self, from: data)
onCompletion(items, nil)// error in this line Cannot convert value of type 'ModelObject?' to expected argument type '_?'
}
Upvotes: 0
Views: 1937
Reputation: 2902
You can create your method something like:
func method1<Model: Codable>(onCompletion: @escaping (Model?, Error?) -> Void) -> Void {
let decoder = JSONDecoder()
let itemObj = try? decoder.decode(Model.self, from: data)
onCompletion(itemObj, nil)
}
And if you have your struct like:
struct ModelObject: Codable {
}
you can call this method like:
method1 { (model: ModelObject?, error) in
}
You have another struct like:
struct AnotherModelObject: Codable {
}
You can call it like:
method1 { (model: AnotherModelObject?, error) in
}
Upvotes: 5
Reputation: 27211
You can hide the protocol inside another struct or you can use a custom container.
protocol Container { }
struct Storage {
let model: Codable
}
struct ModelObject: Codable, Container {
}
enum Result<T> {
case data(result: T)
}
typealias completionHandler = ([Storage]?, Error?) -> Void
func method1(onCompletion: @escaping completionHandler) -> Void {
onCompletion([Storage(model:ModelObject())], nil)
}
func method2(onCompletion: @escaping ([Result<Codable>]) -> Void) -> Void {
onCompletion([Result.data(result: ModelObject() as Codable)])
}
method1 { result, _ in
print(result![0].model)
}
method2 { result in
print(result[0])
}
Upvotes: 1