I have a protocol that I defined like so:
protocol MyProtocol {
...
}
I also have a generic struct:
struct MyStruct <
A modern answer will be like this: (Swift 5.1)
func myFunc < T: MyProtocol> (s: MyStruct<T>) -> T? { ... }
I have to say @Alex want to check if T
type conforms to protocol rather than s
. And some answerer didn't see clearly.
Check T
type conforms to protocol like this :
if let _ = T.self as? MyProtocol.Type {
// T conform MyProtocol
}
or
if T.self is MyProtocol.Type {
// T conform MyProtocol
}
The simplest answer is: don’t do that. Use overloading and constraints instead, and determine everything up-front at compile-time rather than testing stuff dynamically at runtime. Runtime type checking and compile-time generics are like steak and ice-cream – both are nice but mixing them is a bit weird.
Consider something like this:
protocol MyProtocol { }
struct MyStruct <T> { let val: T }
func myFunc<T: MyProtocol>(s: MyStruct<T>) -> T? {
return s.val
}
func myFunc<T>(s: MyStruct<T>) -> T? {
return nil
}
struct S1: MyProtocol { }
struct S2 { }
let m1 = MyStruct(val: S1())
let m2 = MyStruct(val: S2())
myFunc(m1) // returns an instance of S1
myFunc(m2) // returns nil, because S2 doesn't implement MyProtocol
The downside being, you can’t establish dynamically if T supports a protocol at runtime:
let o: Any = S1()
let m3 = MyStruct(val: o)
myFunc(m3) // will return nil even though o
// does actually implement MyProtocol
But, in all honesty, do you really need to do that inside your generic function? If you’re unsure what actual type something is, the better option may be to figure that out up-front rather than deferring it to later and prodding it inside a generic function to find out.
you can also leverage swift's switch case pattern matching, if you want to handle multiple cases of type T
:
func myFunc<T>(s: MyStruct<T>) -> T? {
switch s {
case let sType as MyProtocol:
// do MyProtocol specific stuff here, using sType
default:
//this does not conform to MyProtocol
...
}
}
let conforms = T.self is MyProtocol.Type
For test cases I check conformance like this:
let conforms: Bool = (Controller.self as Any) is Protocol.Type