Reputation: 32529
Please consider this setup:
protocol MyProcotol {
}
class MyModel: MyProcotol {
}
enum Result<T> {
case success(value: T)
case failure
}
class Test {
func test<T: MyProcotol>(completion: (Result<T>) -> Void) {
let model = MyModel()
let result = Result.success(value: model)
completion(result)
}
}
Why can't I call completion(result)
? I'm getting this error:
Cannot convert value of type 'Result' to expected argument type 'Result<_>'
Any workaround?
Upvotes: 11
Views: 14919
Reputation: 12687
You can convert your potential generic value with force cast.
protocol MyProcotol {}
struct MyModel: MyProcotol {
let x: Int
}
struct TheirModel: MyProcotol {
let y: Int
}
enum Result<T> {
case success(value: T)
case failure
var value: T? {
switch self {
case .success(let value): return value
case .failure: return nil
}
}
}
struct Test {
enum ModelType {
case my, their
}
static func get<T: MyProcotol>(type: ModelType, completion: (Result<T>) -> Void) {
let model: Any
switch type {
case .my: model = MyModel(x: 42)
case .their: model = TheirModel(y: 19)
}
if let value = model as? T { completion(.success(value: value)) }
else { completion(.failure) }
}
}
Test.get(type: .my) { (result: Result<MyModel>) in
guard let value = result.value else { return }
print("here is MyModel \(value) with value: \(value.x)")
}
Test.get(type: .their) { (result: Result<TheirModel>) in
guard let value = result.value else { return }
print("here is TheirModel \(value) with value: \(value.y)")
}
Test.get(type: .their) { (value: Result<MyModel>) in
print("here is failure? \(value)")
}
Upvotes: 3
Reputation: 285200
You are using a non-generic concrete type MyModel
in a generic function, that doesn't work.
You could do something like this
class Test {
func test<T: MyProcotol>(item: T, completion: (Result<T>) -> Void) {
let result : Result<T> = .success(value: item)
completion(result)
}
}
Upvotes: 10