Checking if the Struct conformed to protocol, but if the nested struct is optional it always returns false
,
example:
protocol XYZ {
}
extension XYZ {
func test() {
print("asdsfd")
}
}
struct Test1: XYZ {
var test2: Test2
var test3: Test3?
init(){
self.test2 = Test2()
self.test3 = Test3()
}
}
struct Test2: XYZ {
}
struct Test3: XYZ {
}
Now: if I want check if the struct is using protocol
let x = Test1()
below condition will be true because Test2
conformed to XYZ
protocol
print(type(of: x.test2) is XYZ.Type)
below condition will be false because Optional<Test2>
conformed to XYZ
protocol should be true
but it's return false
because of optional
print(type(of: x.test3) is XYZ.Type)
how should I handle the optional in this case, I tried by unwrapping optional but it's not happening. any help is appreciated.
I tried to unwrap the optional but it's not happening. I am trying to find a way to compare the optional type conforms to protocol.
CodePudding user response:
See The Swift Programming Language: Protocols: Checking for Protocol Conformance, in which the is
, as?
and as!
operators can check for conformance directly, without needing to extract the type(of:)
:
Checking for Protocol Conformance
You can use the
is
andas
operators described in Type Casting to check for protocol conformance, and to cast to a specific protocol. Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a type:
The
is
operator returnstrue
if an instance conforms to a protocol and returnsfalse
if it doesn’t.The
as?
version of the downcast operator returns an optional value of the protocol’s type, and this value isnil
if the instance doesn’t conform to that protocol.The
as!
version of the downcast operator forces the downcast to the protocol type and triggers a runtime error if the downcast doesn’t succeed.
So, rather than:
print(type(of: x.test2) is XYZ.Type) // true
print(type(of: x.test3) is XYZ.Type) // false
You can avoid type(of:)
and test the conformance directly (which handles optionals):
print(x.test2 is XYZ) // true
print(x.test3 is XYZ) // true
CodePudding user response:
When checking for protocol conformance don't use Protocol.Type
protocol XYZ {
}
extension XYZ {
func test() {
print("asdsfd")
}
}
struct Test1: XYZ {
var test2: Test2
var test3: Test3?
init(){
self.test2 = Test2()
self.test3 = Test3()
}
}
struct Test2: XYZ {
}
struct Test3: XYZ {
}
let x = Test1()
// does Test1 conform to XYZ?
print(x is XYZ)
// Does x.test2 conform to the protocol?
print(x.test2 is XYZ)
// Does x.test3 conform to the protocol?
print(x.test3 is XYZ)
// The above prints true, we're seeing if it can be an XYZ, but if we test like you do
print(x.test3 is XYZ.Type)
// This is false, as you said in your example.
In real coding scenarios you're going to be using
if let example = x.test3 as? MyProtocol { ... }
I can't think of a common scenario I've run into where I've ever needed to compare against a Protocol.Type
.
Also, in this example at least, all this testing is not needed because the compiler knows ahead of time. To make an example where it wouldn't:
let y: Any = x.test3
if let y = y as? XYZ {
print("Test")
}
Here the compiler doesn't know that y conforms to the protocol, as its type is Any
, but we can try and cast it - which we can see does work.