I\'m writing a helper function in Swift for use in SpriteKit games that will check if the collision detention has been set up correctly.
I want to check that my GameScen
respondsToSelector fails, because it expects an instance of SKPhysicsContact and not SKPhysicsContact.type.
To check if an object implements an interface, you can use is. So for example:
protocol Test {
func foo();
}
class TestImpl : Test {
func foo() {
print("bar")
}
}
let a = TestImpl()
let b = String()
print(a is Test) // true
print(b is Test) // false
You are still thinking in Objective-C, embrace Swift!
Assuming that your protocol looks like this:
@objc protocol SKPhysicsContactDelegate {
optional func didBeginContact()
}
Try this:
if let delegate = gameScene as? SKPhysicsContactDelegate {
delegate.didBeginContact?()
}
Or a one liner:
(gameScene as? SKPhysicsContactDelegate)?.didBeginContact?()
Notice the ?
after the method name in the call? It's because that method is optional and it won't get called if the object doesn't implement that method. And the if let
branch won't get executed if the object doesn't conforms to SKPhysicsContactDeletegate
protocol.
To check the existence of the method itself before calling, just omit the method call to get a reference to that methodand check it like any other variable:
if let method = (gameScene as? SKPhysicsContactDelegate)?.didBeginContact {
print("gameScene conforms to SKPhysicsContactDelegate and implements didBeginContact")
// Call it later whenever you want
method()
}
If you don't need to call it later, just check for nil
:
if (gameScene as? SKPhysicsContactDelegate)?.didBeginContact != nil {
print("gameScene conforms to SKPhysicsContactDelegate and implements didBeginContact")
}
Checking for optional static
methods uses the same approach, but requires the class object instead of an instance of the class:
if (GameScene.self as? OptionalProtocol.Type)?.staticMethod != nil {
print("gameScene conforms to OptionalProtocol and implements staticMethod")
}
Notice GameScene.self
for obtaining the object type and <protocol>.Type
to cast to the protocol class instead of a protocol instance.
Attached full sample for Playgrounds, Swift script or any online Swift compiler:
import Foundation
@objc protocol OptionalProtocol {
optional func instanceMethod()
optional static func staticMethod()
}
class Nothing {}
class Something: OptionalProtocol {}
class Bar: NSObject, OptionalProtocol {
func instanceMethod() {
print("Instance method")
}
}
class Foo: NSObject, OptionalProtocol {
static func staticMethod() {
print("Static method")
}
}
// Cast instances to 'Any' and classes to 'AnyClass'
let nothing: Any = Nothing()
let nothingClass: AnyClass = Nothing.self
let something: Any = Something()
let somethingClass: AnyClass = Something.self
let bar: Any = Bar()
let barClass: AnyClass = Bar.self
let foo: Any = Foo()
let fooClass: AnyClass = Foo.self
nothing is OptionalProtocol // false
(nothing as? OptionalProtocol)?.instanceMethod != nil // false
(nothing as? OptionalProtocol)?.instanceMethod?() // Does nothing
(nothingClass as? OptionalProtocol.Type)?.staticMethod != nil // false
(nothingClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing
something is OptionalProtocol // true
(something as? OptionalProtocol)?.instanceMethod != nil // false
(something as? OptionalProtocol)?.instanceMethod?() // Does nothing
(somethingClass as? OptionalProtocol.Type)?.staticMethod != nil // false
(somethingClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing
bar is OptionalProtocol // true
(bar as? OptionalProtocol)?.instanceMethod != nil // true
(bar as? OptionalProtocol)?.instanceMethod?() // Prints 'Instance method'
(barClass as? OptionalProtocol.Type)?.staticMethod != nil // false
(barClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Does nothing
foo is OptionalProtocol // true
(foo as? OptionalProtocol)?.instanceMethod != nil // false
(foo as? OptionalProtocol)?.instanceMethod?() // Does nothing
(fooClass as? OptionalProtocol.Type)?.staticMethod != nil // true
(fooClass as? OptionalProtocol.Type)?.staticMethod?() != nil // Prints 'Static method'